summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rw-r--r--mysys/charset.c194
-rw-r--r--mysys/default.c39
-rw-r--r--mysys/hash.c2
-rw-r--r--mysys/mf_path.c3
-rw-r--r--mysys/my_bit.c42
-rw-r--r--mysys/my_pthread.c23
-rw-r--r--mysys/my_seek.c3
-rw-r--r--mysys/my_semaphore.c4
-rw-r--r--mysys/raid.cc4
-rw-r--r--mysys/thr_alarm.c136
10 files changed, 241 insertions, 209 deletions
diff --git a/mysys/charset.c b/mysys/charset.c
index 097c35caa56..ad0468a5087 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -120,45 +120,15 @@ static void simple_cs_init_functions(CHARSET_INFO *cs)
if (cs->state & MY_CS_BINSORT)
{
- CHARSET_INFO *b= &my_charset_bin;
- cs->strnxfrm = b->strnxfrm;
- cs->like_range = b->like_range;
- cs->wildcmp = b->wildcmp;
- cs->strnncoll = b->strnncoll;
- cs->strnncollsp = b->strnncollsp;
- cs->strcasecmp = b->strcasecmp;
- cs->hash_sort = b->hash_sort;
+ cs->coll= &my_collation_bin_handler;
}
else
{
- cs->strnxfrm = my_strnxfrm_simple;
- cs->like_range = my_like_range_simple;
- cs->wildcmp = my_wildcmp_8bit;
- cs->strnncoll = my_strnncoll_simple;
- cs->strnncollsp = my_strnncollsp_simple;
- cs->strcasecmp = my_strcasecmp_8bit;
- cs->hash_sort = my_hash_sort_simple;
+ cs->coll= &my_collation_8bit_simple_ci_handler;
}
- cs->caseup_str = my_caseup_str_8bit;
- cs->casedn_str = my_casedn_str_8bit;
- cs->caseup = my_caseup_8bit;
- cs->casedn = my_casedn_8bit;
- cs->mb_wc = my_mb_wc_8bit;
- cs->wc_mb = my_wc_mb_8bit;
- cs->snprintf = my_snprintf_8bit;
- cs->long10_to_str= my_long10_to_str_8bit;
- cs->longlong10_to_str= my_longlong10_to_str_8bit;
- cs->fill = my_fill_8bit;
- cs->strntol = my_strntol_8bit;
- cs->strntoul = my_strntoul_8bit;
- cs->strntoll = my_strntoll_8bit;
- cs->strntoull = my_strntoull_8bit;
- cs->strntod = my_strntod_8bit;
- cs->scan = my_scan_8bit;
+ cs->cset= &my_charset_8bit_handler;
cs->mbmaxlen = 1;
- cs->numchars = my_numchars_8bit;
- cs->charpos = my_charpos_8bit;
}
@@ -313,6 +283,8 @@ static int add_collation(CHARSET_INFO *cs)
{
if (!all_charsets[cs->number])
{
+ if (cs->state & MY_CS_COMPILED)
+ goto clear;
if (!(all_charsets[cs->number]=
(CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0))))
return MY_XML_ERROR;
@@ -327,10 +299,10 @@ static int add_collation(CHARSET_INFO *cs)
if (!(all_charsets[cs->number]->state & MY_CS_COMPILED))
{
+ simple_cs_init_functions(all_charsets[cs->number]);
simple_cs_copy_data(all_charsets[cs->number],cs);
if (simple_cs_is_full(all_charsets[cs->number]))
{
- simple_cs_init_functions(all_charsets[cs->number]);
all_charsets[cs->number]->state |= MY_CS_LOADED;
}
}
@@ -341,6 +313,7 @@ static int add_collation(CHARSET_INFO *cs)
if (cs->comment)
dst->comment= my_once_strdup(cs->comment,MYF(MY_WME));
}
+clear:
cs->number= 0;
cs->primary_number= 0;
cs->binary_number= 0;
@@ -423,56 +396,63 @@ static my_bool init_compiled_charsets(myf flags __attribute__((unused)))
{
CHARSET_INFO *cs;
- MY_ADD_CHARSET(&my_charset_latin1);
-
MY_ADD_CHARSET(&my_charset_bin);
+
+ MY_ADD_CHARSET(&my_charset_latin1);
+ MY_ADD_CHARSET(&my_charset_latin1_bin);
+ MY_ADD_CHARSET(&my_charset_latin1_german2_ci);
#ifdef HAVE_CHARSET_big5
- MY_ADD_CHARSET(&my_charset_big5);
+ MY_ADD_CHARSET(&my_charset_big5_chinese_ci);
+ MY_ADD_CHARSET(&my_charset_big5_bin);
#endif
-#ifdef HAVE_CHARSET_czech
- MY_ADD_CHARSET(&my_charset_czech);
+#ifdef HAVE_CHARSET_cp1250
+ MY_ADD_CHARSET(&my_charset_cp1250_czech_ci);
#endif
-#ifdef HAVE_CHARSET_euc_kr
- MY_ADD_CHARSET(&my_charset_euc_kr);
+#ifdef HAVE_CHARSET_latin2
+ MY_ADD_CHARSET(&my_charset_latin2_czech_ci);
#endif
-#ifdef HAVE_CHARSET_gb2312
- MY_ADD_CHARSET(&my_charset_gb2312);
+#ifdef HAVE_CHARSET_euckr
+ MY_ADD_CHARSET(&my_charset_euckr_korean_ci);
+ MY_ADD_CHARSET(&my_charset_euckr_bin);
#endif
-#ifdef HAVE_CHARSET_gbk
- MY_ADD_CHARSET(&my_charset_gbk);
+#ifdef HAVE_CHARSET_gb2312
+ MY_ADD_CHARSET(&my_charset_gb2312_chinese_ci);
+ MY_ADD_CHARSET(&my_charset_gb2312_bin);
#endif
-#ifdef HAVE_CHARSET_latin1_de
- MY_ADD_CHARSET(&my_charset_latin1_de);
+#ifdef HAVE_CHARSET_gbk
+ MY_ADD_CHARSET(&my_charset_gbk_chinese_ci);
+ MY_ADD_CHARSET(&my_charset_gbk_bin);
#endif
#ifdef HAVE_CHARSET_sjis
- MY_ADD_CHARSET(&my_charset_sjis);
+ MY_ADD_CHARSET(&my_charset_sjis_japanese_ci);
+ MY_ADD_CHARSET(&my_charset_sjis_bin);
#endif
#ifdef HAVE_CHARSET_tis620
- MY_ADD_CHARSET(&my_charset_tis620);
+ MY_ADD_CHARSET(&my_charset_tis620_thai_ci);
+ MY_ADD_CHARSET(&my_charset_tis620_bin);
#endif
#ifdef HAVE_CHARSET_ucs2
- MY_ADD_CHARSET(&my_charset_ucs2);
+ MY_ADD_CHARSET(&my_charset_ucs2_general_ci);
+ MY_ADD_CHARSET(&my_charset_ucs2_bin);
#endif
#ifdef HAVE_CHARSET_ujis
- MY_ADD_CHARSET(&my_charset_ujis);
+ MY_ADD_CHARSET(&my_charset_ujis_japanese_ci);
+ MY_ADD_CHARSET(&my_charset_ujis_bin);
#endif
#ifdef HAVE_CHARSET_utf8
- MY_ADD_CHARSET(&my_charset_utf8);
-#endif
-
-#ifdef HAVE_CHARSET_win1250ch
- MY_ADD_CHARSET(&my_charset_win1250ch);
+ MY_ADD_CHARSET(&my_charset_utf8_general_ci);
+ MY_ADD_CHARSET(&my_charset_utf8_bin);
#endif
/* Copy compiled charsets */
@@ -533,12 +513,6 @@ void free_charsets(void)
}
-static void get_charset_conf_name(const char *cs_name, char *buf)
-{
- strxmov(get_charsets_dir(buf), cs_name, ".conf", NullS);
-}
-
-
uint get_charset_number(const char *charset_name)
{
CHARSET_INFO **cs;
@@ -548,9 +522,7 @@ uint get_charset_number(const char *charset_name)
for (cs= all_charsets; cs < all_charsets+255; ++cs)
{
if ( cs[0] && cs[0]->name &&
- (!my_strcasecmp(&my_charset_latin1, cs[0]->name, charset_name) ||
- (!my_strcasecmp(&my_charset_latin1, cs[0]->csname, charset_name) &&
- (cs[0]->state & MY_CS_PRIMARY))))
+ !my_strcasecmp(&my_charset_latin1, cs[0]->name, charset_name))
return cs[0]->number;
}
return 0; /* this mimics find_type() */
@@ -663,95 +635,3 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
return cs;
}
-
-
-/* Only append name if it doesn't exist from before */
-
-static my_bool charset_in_string(const char *name, DYNAMIC_STRING *s)
-{
- uint length= (uint) strlen(name);
- const char *pos;
- for (pos=s->str ; (pos=strstr(pos,name)) ; pos++)
- {
- if (! pos[length] || pos[length] == ' ')
- return TRUE; /* Already existed */
- }
- return FALSE;
-}
-
-
-static void charset_append(DYNAMIC_STRING *s, const char *name)
-{
- if (!charset_in_string(name, s))
- {
- dynstr_append(s, name);
- dynstr_append(s, " ");
- }
-}
-
-
-/* Returns a dynamically-allocated string listing the character sets
- requested. The caller is responsible for freeing the memory. */
-
-char *list_charsets(myf want_flags)
-{
- DYNAMIC_STRING s;
- char *p;
-
- (void)init_available_charsets(MYF(0));
- init_dynamic_string(&s, NullS, 256, 1024);
-
- if (want_flags & MY_CS_COMPILED)
- {
- CHARSET_INFO **cs;
- for (cs= all_charsets; cs < all_charsets+255; cs++)
- {
- if (cs[0])
- {
- dynstr_append(&s, cs[0]->name);
- dynstr_append(&s, " ");
- }
- }
- }
-
- if (want_flags & MY_CS_CONFIG)
- {
- CHARSET_INFO **cs;
- char buf[FN_REFLEN];
- MY_STAT status;
-
- for (cs=all_charsets; cs < all_charsets+255; cs++)
- {
- if (!cs[0] || !cs[0]->name || charset_in_string(cs[0]->name, &s))
- continue;
- get_charset_conf_name(cs[0]->name, buf);
- if (!my_stat(buf, &status, MYF(0)))
- continue; /* conf file doesn't exist */
- dynstr_append(&s, cs[0]->name);
- dynstr_append(&s, " ");
- }
- }
-
- if (want_flags & (MY_CS_INDEX|MY_CS_LOADED))
- {
- CHARSET_INFO **cs;
- for (cs= all_charsets; cs < all_charsets + 255; cs++)
- if (cs[0] && cs[0]->name && (cs[0]->state & want_flags) )
- charset_append(&s, cs[0]->name);
- }
-
- if (s.length)
- {
- s.str[s.length - 1]= '\0'; /* chop trailing space */
- p= my_strdup(s.str, MYF(MY_WME));
- }
- else
- {
- p= my_strdup("", MYF(MY_WME));
- }
- dynstr_free(&s);
-
- return p;
-}
-
-
diff --git a/mysys/default.c b/mysys/default.c
index 9fedfd795a5..a592e8b42e1 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -72,6 +72,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
const char *dir, const char *config_file,
const char *ext, TYPELIB *group);
+static char *remove_end_comment(char *ptr);
void load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
@@ -174,8 +175,6 @@ void load_defaults(const char *conf_file, const char **groups,
res= (char**) (ptr+sizeof(alloc));
/* copy name + found arguments + command line arguments to new array */
- res[0]=*argc ? argv[0][0] : "";
-
memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*));
/* Skipp --defaults-file and --defaults-extra-file */
(*argc)-= args_used;
@@ -251,7 +250,13 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(0)))
return 0;
- if (stat_info.st_mode & S_IWOTH) /* ignore world-writeable files */
+ /*
+ Ignore world-writable regular files.
+ This is mainly done to protect us to not read a file created by
+ the mysqld server, but the check is still valid in most context.
+ */
+ if ((stat_info.st_mode & S_IWOTH) &&
+ (stat_info.st_mode & S_IFMT) == S_IFREG)
{
fprintf(stderr, "warning: World-writeable config file %s is ignored\n",
name);
@@ -293,8 +298,9 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
if (!read_values)
continue;
- if (!(end=value=strchr(ptr,'=')))
- end=strend(ptr); /* Option without argument */
+ end= remove_end_comment(ptr);
+ if ((value= strchr(ptr, '=')))
+ end= value; /* Option without argument */
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
if (!value)
{
@@ -364,6 +370,29 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
+static char *remove_end_comment(char *ptr)
+{
+ char quote= 0;
+
+ for (; *ptr; ptr++)
+ {
+ if (*ptr == '\'' || *ptr == '\"')
+ {
+ if (!quote)
+ quote= *ptr;
+ else if (quote == *ptr)
+ quote= 0;
+ }
+ if (!quote && *ptr == '#') /* We are not inside a comment */
+ {
+ *ptr= 0;
+ return ptr;
+ }
+ }
+ return ptr;
+}
+
+
void print_defaults(const char *conf_file, const char **groups)
{
#ifdef __WIN__
diff --git a/mysys/hash.c b/mysys/hash.c
index 9169613c39f..0b2dbc484bc 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -36,7 +36,7 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length);
static uint calc_hash(HASH *hash,const byte *key,uint length)
{
ulong nr1=1, nr2=4;
- hash->charset->hash_sort(hash->charset,key,length,&nr1,&nr2);
+ hash->charset->coll->hash_sort(hash->charset,key,length,&nr1,&nr2);
return nr1;
}
diff --git a/mysys/mf_path.c b/mysys/mf_path.c
index 23eadd2acce..1ecd5fbb2b1 100644
--- a/mysys/mf_path.c
+++ b/mysys/mf_path.c
@@ -77,6 +77,9 @@ my_string my_path(my_string to, const char *progname,
#define F_OK 0
#define PATH_SEP ';'
#define PROGRAM_EXTENSION ".exe"
+#elif defined(__NETWARE__)
+#define PATH_SEP ';'
+#define PROGRAM_EXTENSION ".nlm"
#else
#define PATH_SEP ':'
#endif
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
index 0ff487afe03..55dd72f5f76 100644
--- a/mysys/my_bit.c
+++ b/mysys/my_bit.c
@@ -29,3 +29,45 @@ uint my_bit_log2(ulong value)
for (bit=0 ; value > 1 ; value>>=1, bit++) ;
return bit;
}
+
+static char nbits[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
+};
+
+uint my_count_bits(ulonglong v)
+{
+#if SIZEOF_LONG_LONG > 4
+ /* The following code is a bit faster on 16 bit machines than if we would
+ only shift v */
+ ulong v2=(ulong) (v >> 32);
+ return (uint) (uchar) (nbits[(uchar) v] +
+ nbits[(uchar) (v >> 8)] +
+ nbits[(uchar) (v >> 16)] +
+ nbits[(uchar) (v >> 24)] +
+ nbits[(uchar) (v2)] +
+ nbits[(uchar) (v2 >> 8)] +
+ nbits[(uchar) (v2 >> 16)] +
+ nbits[(uchar) (v2 >> 24)]);
+#else
+ return (uint) (uchar) (nbits[(uchar) v] +
+ nbits[(uchar) (v >> 8)] +
+ nbits[(uchar) (v >> 16)] +
+ nbits[(uchar) (v >> 24)]);
+#endif
+}
+
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index 1eb15d92bc9..4f472f61593 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -90,6 +90,29 @@ void *my_pthread_getspecific_imp(pthread_key_t key)
}
#endif
+#ifdef __NETWARE__
+/*
+don't kill the LibC Reaper thread or the main thread
+*/
+#include <nks/thread.h>
+#undef pthread_exit
+void my_pthread_exit(void *status)
+{
+ NXThreadId_t tid = NXThreadGetId();
+ NXContext_t ctx;
+ char name[PATH_MAX] = "";
+
+ NXThreadGetContext(tid, &ctx);
+ NXContextGetName(ctx, name, PATH_MAX);
+
+ // "MYSQLD.NLM's LibC Reaper" or "MYSQLD.NLM's main thread"
+ // with a debug build of LibC the reaper can have different names
+ if (!strindex(name, "\'s"))
+ {
+ pthread_exit(status);
+ }
+}
+#endif
/* Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7
(and DEC OSF/1 3.2 too) */
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index 177a5cee953..ec24a26b3d9 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -15,6 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
+#include <assert.h>
/* Seek to position in file */
/*ARGSUSED*/
@@ -27,6 +28,8 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d",
fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos,
whence, MyFlags));
+ DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */
+
newpos=lseek(fd, pos, whence);
if (newpos == (os_off_t) -1)
{
diff --git a/mysys/my_semaphore.c b/mysys/my_semaphore.c
index 2dd224cd99e..aa216cbc289 100644
--- a/mysys/my_semaphore.c
+++ b/mysys/my_semaphore.c
@@ -23,7 +23,7 @@
#include <my_semaphore.h>
#include <errno.h>
-#if !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H)
+#if !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) && defined(THREAD)
int sem_init(sem_t * sem, int pshared, uint value)
{
@@ -101,4 +101,4 @@ int sem_getvalue(sem_t * sem, uint *sval)
return 0;
}
-#endif /* !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) */
+#endif /* !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) && defined(THREAD) */
diff --git a/mysys/raid.cc b/mysys/raid.cc
index d6359dc0f93..0b688464fb3 100644
--- a/mysys/raid.cc
+++ b/mysys/raid.cc
@@ -157,10 +157,10 @@ extern "C" {
DBUG_PRINT("enter",("Fd: %d pos: %lu whence: %d MyFlags: %d",
fd, (ulong) pos, whence, MyFlags));
- assert(pos != MY_FILEPOS_ERROR);
-
if (is_raid(fd))
{
+ assert(pos != MY_FILEPOS_ERROR);
+
RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**));
DBUG_RETURN(raid->Seek(pos,whence,MyFlags));
}
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index add5335a7af..7a845e3eb00 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -27,6 +27,7 @@
#include <m_string.h>
#include <queues.h>
#include "thr_alarm.h"
+#include <assert.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> /* AIX needs this for fd_set */
@@ -36,21 +37,22 @@
#define ETIME ETIMEDOUT
#endif
-static my_bool alarm_aborted=1;
-my_bool thr_alarm_inited=0;
+static int alarm_aborted=1; /* No alarm thread */
+my_bool thr_alarm_inited= 0;
+volatile my_bool alarm_thread_running= 0;
static sig_handler process_alarm_part2(int sig);
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
static pthread_mutex_t LOCK_alarm;
+static pthread_cond_t COND_alarm;
static sigset_t full_signal_set;
static QUEUE alarm_queue;
static uint max_used_alarms=0;
pthread_t alarm_thread;
#ifdef USE_ALARM_THREAD
-static pthread_cond_t COND_alarm;
static void *alarm_handler(void *arg);
#define reschedule_alarms() pthread_cond_signal(&COND_alarm)
#else
@@ -77,6 +79,7 @@ void init_thr_alarm(uint max_alarms)
compare_ulong,NullS);
sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&COND_alarm,NULL);
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
#if defined(HAVE_mit_thread)
sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */
@@ -96,7 +99,6 @@ void init_thr_alarm(uint max_alarms)
{
pthread_attr_t thr_attr;
pthread_attr_init(&thr_attr);
- pthread_cond_init(&COND_alarm,NULL);
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&thr_attr,8196);
@@ -120,12 +122,24 @@ void init_thr_alarm(uint max_alarms)
/*
Request alarm after sec seconds.
- A pointer is returned with points to a non-zero int when the alarm has been
- given. This can't be called from the alarm-handling thread.
- Returns 0 if no more alarms are allowed (aborted by process)
+
+ SYNOPSIS
+ thr_alarm()
+ alrm Pointer to alarm detection
+ alarm_data Structure to store in alarm queue
+
+ NOTES
+ This function can't be called from the alarm-handling thread.
+
+ RETURN VALUES
+ 0 ok
+ 1 If no more alarms are allowed (aborted by process)
+
+ Stores in first argument a pointer to a non-zero int which is set to 0
+ when the alarm has been given
*/
-bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
+my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
{
ulong now;
sigset_t old_mask;
@@ -136,19 +150,24 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
now=(ulong) time((time_t*) 0);
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
- if (alarm_aborted)
+ if (alarm_aborted > 0)
{ /* No signal thread */
DBUG_PRINT("info", ("alarm aborted"));
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
}
+ if (alarm_aborted < 0)
+ sec= 1; /* Abort mode */
+
if (alarm_queue.elements >= max_used_alarms)
{
if (alarm_queue.elements == alarm_queue.max_elements)
{
DBUG_PRINT("info", ("alarm queue full"));
fprintf(stderr,"Warning: thr_alarm queue is full\n");
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
@@ -163,6 +182,7 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
{
DBUG_PRINT("info", ("failed my_malloc()"));
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
@@ -201,7 +221,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
ALARM *alarm_data;
sigset_t old_mask;
uint i;
- bool found=0;
+ my_bool found=0;
DBUG_ENTER("thr_end_alarm");
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
@@ -219,23 +239,16 @@ void thr_end_alarm(thr_alarm_t *alarmed)
break;
}
}
+ DBUG_ASSERT(!*alarmed || found);
if (!found)
{
-#ifdef MAIN
- printf("Warning: Didn't find alarm %lx in queue of %d alarms\n",
- (long) *alarmed, alarm_queue.elements);
-#endif
+ if (*alarmed)
+ fprintf(stderr,"Warning: Didn't find alarm %lx in queue of %d alarms\n",
+ (long) *alarmed, alarm_queue.elements);
DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",
(long) *alarmed));
}
- if (alarm_aborted && !alarm_queue.elements)
- {
- delete_queue(&alarm_queue);
- pthread_mutex_unlock(&LOCK_alarm);
- pthread_mutex_destroy(&LOCK_alarm);
- }
- else
- pthread_mutex_unlock(&LOCK_alarm);
+ pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_VOID_RETURN;
}
@@ -365,31 +378,66 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
/*
- Shedule all alarms now.
- When all alarms are given, Free alarm memory and don't allow more alarms.
+ Schedule all alarms now and optionally free all structures
+
+ SYNPOSIS
+ end_thr_alarm()
+ free_structures Set to 1 if we should free memory used for
+ the alarm queue.
+ When we call this we should KNOW that there
+ is no active alarms
+ IMPLEMENTATION
+ Set alarm_abort to -1 which will change the behavior of alarms as follows:
+ - All old alarms will be rescheduled at once
+ - All new alarms will be rescheduled to one second
*/
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
- if (!alarm_aborted)
+ if (alarm_aborted != 1) /* If memory not freed */
{
- my_bool deleted=0;
pthread_mutex_lock(&LOCK_alarm);
DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
- alarm_aborted=1; /* mark aborted */
- if (!alarm_queue.elements)
+ alarm_aborted= -1; /* mark aborted */
+ if (alarm_queue.elements || (alarm_thread_running && free_structures))
{
- deleted= 1;
- delete_queue(&alarm_queue);
+ if (pthread_equal(pthread_self(),alarm_thread))
+ alarm(1); /* Shut down everything soon */
+ else
+ reschedule_alarms();
+ }
+ if (free_structures)
+ {
+ struct timespec abstime;
+ /*
+ The following test is just for safety, the caller should not
+ depend on this
+ */
+ DBUG_ASSERT(!alarm_queue.elements);
+ /* Wait until alarm thread dies */
+
+ set_timespec(abstime, 10); /* Wait up to 10 seconds */
+ while (alarm_thread_running)
+ {
+ int error= pthread_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime);
+ if (error == ETIME || error == ETIMEDOUT)
+ break; /* Don't wait forever */
+ }
+ if (!alarm_queue.elements)
+ {
+ delete_queue(&alarm_queue);
+ alarm_aborted= 1;
+ pthread_mutex_unlock(&LOCK_alarm);
+ if (!alarm_thread_running) /* Safety */
+ {
+ pthread_mutex_destroy(&LOCK_alarm);
+ pthread_cond_destroy(&COND_alarm);
+ }
+ }
}
- if (pthread_equal(pthread_self(),alarm_thread))
- alarm(1); /* Shut down everything soon */
else
- reschedule_alarms();
- pthread_mutex_unlock(&LOCK_alarm);
- if (deleted)
- pthread_mutex_destroy(&LOCK_alarm);
+ pthread_mutex_unlock(&LOCK_alarm);
}
DBUG_VOID_RETURN;
}
@@ -471,6 +519,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
puts("Starting alarm thread");
#endif
my_thread_init();
+ alarm_thread_running= 1;
pthread_mutex_lock(&LOCK_alarm);
for (;;)
{
@@ -495,7 +544,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
}
}
}
- else if (alarm_aborted)
+ else if (alarm_aborted == -1)
break;
else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm)))
{
@@ -507,6 +556,8 @@ static void *alarm_handler(void *arg __attribute__((unused)))
process_alarm(0);
}
bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
+ alarm_thread_running= 0;
+ pthread_cond_signal(&COND_alarm);
pthread_mutex_unlock(&LOCK_alarm);
pthread_exit(0);
return 0; /* Impossible */
@@ -629,7 +680,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr)
}
}
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */
@@ -708,7 +759,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr)
}
}
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */
@@ -907,7 +958,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
case SIGHUP:
#endif
printf("Aborting nicely\n");
- end_thr_alarm();
+ end_thr_alarm(0);
break;
#ifdef SIGTSTP
case SIGTSTP:
@@ -1004,10 +1055,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
if (thread_count == 1)
{
printf("Calling end_thr_alarm. This should cancel the last thread\n");
- end_thr_alarm();
+ end_thr_alarm(0);
}
}
pthread_mutex_unlock(&LOCK_thread_count);
+ end_thr_alarm(1);
thr_alarm_info(&alarm_info);
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
alarm_info.active_alarms, alarm_info.max_used_alarms,