diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 88ba2af3b..6df906812 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +2001-11-27 Christopher Faylor + + * cygwin.din (ualarm): New export. + * dcrt0.cc (_dll_crt0): Add experimental tls storage declaration. + (dll_crt0): Ditto. + * debug.cc (thread_stub): Ditto. + * thread.cc: Minor cleanup. + (__pthread_create): Add experimental tls storage declaration. + * miscfuncs.cc: Define tls index. + * winsup.h: Declare experimental tls storage. + + * window.cc (alarm): Use old timer return from setitimer. + (ualarm): New function. + 2001-11-26 Christopher Faylor * Makefile.in (libcygwin.a): Use ar commands to build libcygwin.a since diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 9fa4d4e3f..dae5fd9d3 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -858,6 +858,8 @@ ttyname _ttyname = ttyname tzset _tzset = tzset +ualarm +_ualarm = ualarm umask _umask = umask uname @@ -866,6 +868,8 @@ ungetc _ungetc = ungetc unlink _unlink = unlink +usleep +_usleep = usleep utime _utime = utime utimes @@ -963,8 +967,6 @@ wcscmp _wcscmp = wcscmp wcslen _wcslen = wcslen -usleep -_usleep = usleep wprintf _wprintf = wprintf memccpy diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 1dfccbedc..84754b250 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -803,6 +803,7 @@ initial_env () extern "C" void __stdcall _dll_crt0 () { + DECLARE_TLS_STORAGE; initial_env (); char zeros[sizeof (fork_info->zero)] = {0}; #ifdef DEBUGGING @@ -853,6 +854,7 @@ _dll_crt0 () void dll_crt0 (per_process *uptr) { + DECLARE_TLS_STORAGE; /* Set the local copy of the pointer into the user space. */ if (uptr && uptr != user_data) { diff --git a/winsup/cygwin/debug.cc b/winsup/cygwin/debug.cc index a25283ee7..400130614 100644 --- a/winsup/cygwin/debug.cc +++ b/winsup/cygwin/debug.cc @@ -82,6 +82,7 @@ thread_start NO_COPY start_buf[NTHREADS] = {{0, NULL,NULL}}; static DWORD WINAPI thread_stub (VOID *arg) { + DECLARE_TLS_STORAGE; LPTHREAD_START_ROUTINE threadfunc = ((thread_start *) arg)->func; VOID *threadarg = ((thread_start *) arg)->arg; diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 6cc03a669..b93a7588b 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -12,7 +12,7 @@ details. */ #include "cygerrno.h" #include -/********************** String Helper Functions ************************/ +long tls_ix; const char case_folded_lower[] NO_COPY = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 4b8867993..eede3b6bb 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -289,7 +289,7 @@ MTinterface::Init (int forked) thread_self_dwTlsIndex = TlsAlloc (); if (thread_self_dwTlsIndex == TLS_OUT_OF_INDEXES) system_printf - ("local storage for thread couldn't be set\nThis means that we are not thread safe!\n"); + ("local storage for thread couldn't be set\nThis means that we are not thread safe!"); } concurrency = 0; @@ -323,21 +323,21 @@ void MTinterface::fixup_after_fork (void) { pthread_mutex *mutex = mutexs; - debug_printf("mutexs is %x\n",mutexs); + debug_printf ("mutexs is %x",mutexs); while (mutex) { mutex->fixup_after_fork (); mutex = mutex->next; } pthread_cond *cond = conds; - debug_printf("conds is %x\n",conds); + debug_printf ("conds is %x",conds); while (cond) { cond->fixup_after_fork (); cond = cond->next; } semaphore *sem = semaphores; - debug_printf("semaphores is %x\n",semaphores); + debug_printf ("semaphores is %x",semaphores); while (sem) { sem->fixup_after_fork (); @@ -375,7 +375,7 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr, function = func; arg = threadarg; - win32_obj_id =::CreateThread (&sec_none_nih, attr.stacksize, + win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize, (LPTHREAD_START_ROUTINE) thread_init_wrapper, this, CREATE_SUSPENDED, &thread_id); @@ -420,14 +420,14 @@ pthread_cond::pthread_cond (pthread_condattr *attr):verifyable_object (PTHREAD_C this->mutex = NULL; this->waiting = 0; - this->win32_obj_id =::CreateEvent (&sec_none_nih, false, /*auto signal reset - which I think is pthreads like ? */ + this->win32_obj_id = ::CreateEvent (&sec_none_nih, false, /*auto signal reset - which I think is pthreads like ? */ false, /*start non signaled */ NULL /*no name */); /*TODO: make a shared mem mutex if out attributes request shared mem cond */ - cond_access=NULL; + cond_access = NULL; if ((temperr = pthread_mutex_init (&this->cond_access, NULL))) { - system_printf ("couldn't init mutex, this %0p errno=%d\n", this, temperr); + system_printf ("couldn't init mutex, this %p errno %d", this, temperr); /*we need the mutex for correct behaviour */ magic = 0; } @@ -461,33 +461,33 @@ pthread_cond::BroadCast () { /* TODO: implement the same race fix as Signal has */ if (pthread_mutex_lock (&cond_access)) - system_printf ("Failed to lock condition variable access mutex, this %0p\n", this); + system_printf ("Failed to lock condition variable access mutex, this %p", this); int count = waiting; if (verifyable_object_isvalid (&mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT) { if (pthread_mutex_unlock (&cond_access)) - system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this); + system_printf ("Failed to unlock condition variable access mutex, this %p", this); /*This isn't and API error - users are allowed to call this when no threads are waiting - system_printf ("Broadcast called with invalid mutex\n"); + system_printf ("Broadcast called with invalid mutex"); */ return; } while (count--) PulseEvent (win32_obj_id); if (pthread_mutex_unlock (&cond_access)) - system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this); + system_printf ("Failed to unlock condition variable access mutex, this %p", this); } void pthread_cond::Signal () { if (pthread_mutex_lock (&cond_access)) - system_printf ("Failed to lock condition variable access mutex, this %0p\n", this); + system_printf ("Failed to lock condition variable access mutex, this %p", this); if (verifyable_object_isvalid (&mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT) { if (pthread_mutex_unlock (&cond_access)) - system_printf ("Failed to unlock condition variable access mutex, this %0p\n", + system_printf ("Failed to unlock condition variable access mutex, this %p", this); return; } @@ -496,7 +496,7 @@ pthread_cond::Signal () /* nothing to signal */ { if (pthread_mutex_unlock (&cond_access)) - system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this); + system_printf ("Failed to unlock condition variable access mutex, this %p", this); return; } PulseEvent (win32_obj_id); @@ -518,7 +518,7 @@ pthread_cond::Signal () } InterlockedDecrement (&waiting); if (pthread_mutex_unlock (&cond_access)) - system_printf ("Failed to unlock condition variable access mutex, this %0p\n", this); + system_printf ("Failed to unlock condition variable access mutex, this %p", this); } int @@ -563,16 +563,16 @@ pthread_cond::TimedWait (DWORD dwMilliseconds) void pthread_cond::fixup_after_fork () { - debug_printf("cond %x in fixup_after_fork\n", this); + debug_printf ("cond %x in fixup_after_fork", this); if (shared != PTHREAD_PROCESS_PRIVATE) - api_fatal("doesn't understand PROCESS_SHARED condition variables\n"); + api_fatal ("doesn't understand PROCESS_SHARED condition variables"); /* FIXME: duplicate code here and in the constructor. */ - this->win32_obj_id =::CreateEvent (&sec_none_nih, false, false, NULL); + this->win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL); if (!win32_obj_id) - api_fatal("failed to create new win32 mutex\n"); + api_fatal ("failed to create new win32 mutex"); #if DETECT_BAD_APPS if (waiting) - api_fatal("Forked() while a condition variable has waiting threads.\nReport to cygwin@cygwin.com\n"); + api_fatal ("Forked () while a condition variable has waiting threads.\nReport to cygwin@cygwin.com"); #else waiting = 0; mutex = NULL; @@ -641,7 +641,7 @@ pthread_key::get () pthread_mutex::pthread_mutex (pthread_mutexattr *attr):verifyable_object (PTHREAD_MUTEX_MAGIC) { /*attr checked in the C call */ - if (attr && attr->pshared==PTHREAD_PROCESS_SHARED) + if (attr && attr->pshared == PTHREAD_PROCESS_SHARED) { // fail magic = 0; @@ -651,7 +651,7 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr):verifyable_object (PTHREA InitializeCriticalSection (&criticalsection); else { - this->win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL); + this->win32_obj_id = ::CreateMutex (&sec_none_nih, false, NULL); if (!win32_obj_id) magic = 0; } @@ -721,21 +721,21 @@ pthread_mutex::UnLock () void pthread_mutex::fixup_after_fork () { - debug_printf("mutex %x in fixup_after_fork\n", this); + debug_printf ("mutex %x in fixup_after_fork", this); if (pshared != PTHREAD_PROCESS_PRIVATE) - api_fatal("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's\n"); + api_fatal ("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's"); /* FIXME: duplicate code here and in the constructor. */ if (wincap.has_try_enter_critical_section ()) - InitializeCriticalSection(&criticalsection); + InitializeCriticalSection (&criticalsection); else { - win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL); + win32_obj_id = ::CreateMutex (&sec_none_nih, false, NULL); if (!win32_obj_id) - api_fatal("pthread_mutex::fixup_after_fork() failed to create new win32 mutex\n"); + api_fatal ("pthread_mutex::fixup_after_fork () failed to create new win32 mutex"); } #if DETECT_BAD_APPS if (condwaits) - api_fatal("Forked() while a mutex has condition variables waiting on it.\nReport to cygwin@cygwin.com\n"); + api_fatal ("Forked () while a mutex has condition variables waiting on it.\nReport to cygwin@cygwin.com"); #else condwaits = 0; #endif @@ -752,7 +752,7 @@ pthread_mutexattr::~pthread_mutexattr () semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MAGIC) { - this->win32_obj_id =::CreateSemaphore (&sec_none_nih, value, LONG_MAX, + this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, value, LONG_MAX, NULL); if (!this->win32_obj_id) magic = 0; @@ -809,13 +809,13 @@ semaphore::Wait () void semaphore::fixup_after_fork () { - debug_printf("sem %x in fixup_after_fork\n", this); + debug_printf ("sem %x in fixup_after_fork", this); if (shared != PTHREAD_PROCESS_PRIVATE) - api_fatal("doesn't understand PROCESS_SHARED semaphores variables\n"); + api_fatal ("doesn't understand PROCESS_SHARED semaphores variables"); /* FIXME: duplicate code here and in the constructor. */ - this->win32_obj_id =::CreateSemaphore (&sec_none_nih, currentvalue, LONG_MAX, NULL); + this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue, LONG_MAX, NULL); if (!win32_obj_id) - api_fatal("failed to create new win32 semaphore\n"); + api_fatal ("failed to create new win32 semaphore"); } verifyable_object::verifyable_object (long verifyer): @@ -891,7 +891,7 @@ thread_init_wrapper (void *_arg) if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent)) system_printf ("local storage for thread couldn't be set"); - /*the OS doesn't check this for <=64 Tls entries (pre win2k) */ + /*the OS doesn't check this for <= 64 Tls entries (pre win2k) */ TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread); #ifdef _CYG_THREAD_FAILSAFE @@ -919,6 +919,7 @@ int __pthread_create (pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { + DECLARE_TLS_STORAGE; if (attr && verifyable_object_isvalid (attr, PTHREAD_ATTR_MAGIC) != VALID_OBJECT) return EINVAL; @@ -1293,7 +1294,7 @@ __pthread_atfork (void (*prepare)(void), void (*parent)(void), void (*child)(voi if (prepcb) { prepcb->cb = prepare; - prepcb->next=(callback *)InterlockedExchangePointer ((LONG *) &MT_INTERFACE->pthread_prepare, (long int) prepcb); + prepcb->next = (callback *)InterlockedExchangePointer ((LONG *) &MT_INTERFACE->pthread_prepare, (long int) prepcb); } if (parentcb) { @@ -1302,7 +1303,7 @@ __pthread_atfork (void (*prepare)(void), void (*parent)(void), void (*child)(voi while (*t) t = &(*t)->next; /*t = pointer to last next in the list */ - parentcb->next=(callback *)InterlockedExchangePointer ((LONG *) t, (long int) parentcb); + parentcb->next = (callback *)InterlockedExchangePointer ((LONG *) t, (long int) parentcb); } if (childcb) { @@ -1311,7 +1312,7 @@ __pthread_atfork (void (*prepare)(void), void (*parent)(void), void (*child)(voi while (*t) t = &(*t)->next; /*t = pointer to last next in the list */ - childcb->next=(callback *)InterlockedExchangePointer ((LONG *) t, (long int) childcb); + childcb->next = (callback *)InterlockedExchangePointer ((LONG *) t, (long int) childcb); } return 0; } @@ -1759,13 +1760,13 @@ __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex, /*if the cond variable is blocked, then the above timer test maybe wrong. *shrug**/ if (pthread_mutex_lock (&(*cond)->cond_access)) - system_printf ("Failed to lock condition variable access mutex, this %0p\n", *cond); + system_printf ("Failed to lock condition variable access mutex, this %p", *cond); if ((*cond)->waiting) if ((*cond)->mutex && ((*cond)->mutex != (*themutex))) { if (pthread_mutex_unlock (&(*cond)->cond_access)) - system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond); + system_printf ("Failed to unlock condition variable access mutex, this %p", *cond); return EINVAL; } InterlockedIncrement (&((*cond)->waiting)); @@ -1773,7 +1774,7 @@ __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex, (*cond)->mutex = (*themutex); InterlockedIncrement (&((*themutex)->condwaits)); if (pthread_mutex_unlock (&(*cond)->cond_access)) - system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond); + system_printf ("Failed to unlock condition variable access mutex, this %p", *cond); rv = (*cond)->TimedWait (waitlength); /* this may allow a race on the mutex acquisition and waits.. * But doing this within the cond access mutex creates a different race @@ -1785,10 +1786,10 @@ __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex, if (last == true) (*cond)->mutex = NULL; if (pthread_mutex_lock (&(*cond)->cond_access)) - system_printf ("Failed to lock condition variable access mutex, this %0p\n", *cond); + system_printf ("Failed to lock condition variable access mutex, this %p", *cond); InterlockedDecrement (&((*themutex)->condwaits)); if (pthread_mutex_unlock (&(*cond)->cond_access)) - system_printf ("Failed to unlock condition variable access mutex, this %0p\n", *cond); + system_printf ("Failed to unlock condition variable access mutex, this %p", *cond); return rv; } @@ -1797,11 +1798,11 @@ extern "C" int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { - if (check_valid_pointer(abstime)) + if (check_valid_pointer (abstime)) return EINVAL; struct timeb currSysTime; long waitlength; - ftime(&currSysTime); + ftime (&currSysTime); waitlength = (abstime->tv_sec - currSysTime.time) *1000; if (waitlength < 0) return ETIMEDOUT; @@ -1945,7 +1946,7 @@ int __pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, int *prioceiling) { - pthread_mutex_t *themutex=(pthread_mutex_t *) mutex; + pthread_mutex_t *themutex = (pthread_mutex_t *) mutex; if (*mutex == PTHREAD_MUTEX_INITIALIZER) __pthread_mutex_init ((pthread_mutex_t *) mutex, NULL); if (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT) diff --git a/winsup/cygwin/winbase.h b/winsup/cygwin/winbase.h new file mode 100644 index 000000000..801badc44 --- /dev/null +++ b/winsup/cygwin/winbase.h @@ -0,0 +1,84 @@ +#include_next "winbase.h" + +#ifndef _WINBASE2_H +#define _WINBASE2_H + +extern __inline__ long ilockincr (long *m) +{ + register int __res; + __asm__ __volatile__ ("\n\ + movl $1,%0\n\ + lock xadd %0,(%1)\n\ + inc %0\n\ + ": "=a" (__res), "=r" (m): "1" (m)); + return __res; +} +extern __inline__ long ilockdecr (long *m) +{ + register int __res; + __asm__ __volatile__ ("\n\ + movl $0xffffffff,%0\n\ + lock xadd %0,(%1)\n\ + dec %0\n\ + ": "=a" (__res), "=r" (m): "1" (m)); + return __res; +} +extern __inline__ long ilockexch (long *t, long v) +{ + register int __res; + __asm__ __volatile__ ("\n\ + movl (%2),%0\n\ +1: lock cmpxchgl %3,(%1)\n\ + jne 1b\n\ + ": "=a" (__res), "=c" (t): "1" (t), "d" (v)); + return __res; +} + +#undef InterlockedIncrement +#define InterlockedIncrement ilockincr +#undef InterlockedDecrement +#define InterlockedDecrement ilockdecr +#undef InterlockedExchange +#define InterlockedExchange ilockexch + +extern long tls_ix; + +extern __inline__ DWORD +my_tlsalloc () +{ + return (DWORD) ilockincr (&tls_ix); +} + +extern __inline__ BOOL +my_tlssetvalue (DWORD ix, void *val) +{ + char **stackbase; + __asm__ volatile ("movl %%fs:4,%0": "=g" (stackbase)); + stackbase[-ix] = (char *) val; + return 1; +} + +extern __inline__ void * +my_tlsgetvalue (DWORD ix) +{ + char **stackbase; + __asm__ volatile ("movl %%fs:4,%0": "=g" (stackbase)); + return stackbase[-ix]; +} + +extern __inline__ BOOL +my_tlsfree (DWORD ix) +{ + /* nothing for now */ + return 1; +} + +#undef TlsAlloc +#define TlsAlloc my_tlsalloc +#undef TlsGetValue +#define TlsGetValue my_tlsgetvalue +#undef TlsSetValue +#define TlsSetValue my_tlssetvalue +#undef TlsFree +#define TlsFree my_tlsfree +#endif /*_WINBASE2_H*/ diff --git a/winsup/cygwin/window.cc b/winsup/cygwin/window.cc index 0554f37df..dbff12b69 100644 --- a/winsup/cygwin/window.cc +++ b/winsup/cygwin/window.cc @@ -150,8 +150,7 @@ window_terminate () SendMessage (ourhwnd, WM_DESTROY, 0, 0); } -extern "C" -int +extern "C" int setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue) { UINT elapse; @@ -195,8 +194,7 @@ setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue) return 0; } -extern "C" -int +extern "C" int getitimer (int which, struct itimerval *value) { UINT elapse, val; @@ -221,27 +219,41 @@ getitimer (int which, struct itimerval *value) elapse = GetTickCount () - start_time; val = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000; val -= elapse; - value->it_value.tv_sec = val/1000; - value->it_value.tv_usec = val%1000; + value->it_value.tv_sec = val / 1000; + value->it_value.tv_usec = val % 1000; return 0; } -extern "C" -unsigned int +extern "C" unsigned int alarm (unsigned int seconds) { int ret; struct itimerval newt, oldt; - getitimer (ITIMER_REAL, &oldt); - newt.it_value.tv_sec = seconds; newt.it_value.tv_usec = 0; newt.it_interval.tv_sec = 0; newt.it_interval.tv_usec = 0; - setitimer (ITIMER_REAL, &newt, NULL); + setitimer (ITIMER_REAL, &newt, &oldt); ret = oldt.it_value.tv_sec; if (ret == 0 && oldt.it_value.tv_usec) ret = 1; return ret; } + +extern "C" useconds_t +ualarm (useconds_t value, useconds_t interval) +{ + struct itimerval timer, otimer; + + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = value; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = interval; + + if (setitimer (ITIMER_REAL, &timer, &otimer) < 0) + return (u_int)-1; + + return (otimer.it_value.tv_sec * 1000000) + otimer.it_value.tv_usec; +} + diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 5f463d0c4..85b7fbe0d 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -272,4 +272,11 @@ extern HMODULE cygwin_hmodule; #define winsock_active (wsadata.wVersion < 512) extern struct WSAData wsadata; +#ifdef EXPCGF +#define DECLARE_TLS_STORAGE char **tls[4096] __attribute__ ((unused)) +#else +#define DECLARE_TLS_STORAGE do {} while (0) +#define _WINBASE2_H +#endif + #endif /* defined __cplusplus */