QUARK  0.9.0
QUARK-QUeuingAndRuntimeforKernels
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
quarkwinthread.c
Go to the documentation of this file.
1 
17 #include "quarkwinthread.h"
18 
19 #include <limits.h>
20 
22 #include <process.h>
23 
24 #include <stdio.h>
25 #include <quark.h>
26 
28 static int quarkwinthread_initialized = 0;
29 
31  return GetCurrentThreadId();
32 }
33 
35  pthread_t pt;
36 
37  pt.hThread = GetCurrentThread();
38  pt.uThId = GetCurrentThreadId();
39  return pt;
40 }
41 
43  if (thread1.uThId == thread2.uThId) // && thread1.hThread == thread2.hThread)
44  return 1;
45  return 0;
46 }
47 
49  *mutex =
50  CreateMutex( NULL,
51  FALSE,
52  NULL
53  );
54 
55  return 0;
56 }
57 
58 static int pthread_mutex_check_for_static_initialization( pthread_mutex_t *mutex ) {
59  int retval = 0;
60  /* This should be called once to initialize some structures */
61  if ( quarkwinthread_initialized == 0 ) {
62  quarkwinthread_initialized = 1;
63  InitializeCriticalSection( &quarkwinthread_static_initializer_check_lock );
64  }
65  EnterCriticalSection( &quarkwinthread_static_initializer_check_lock );
66  if ( *mutex == PTHREAD_MUTEX_INITIALIZER )
67  retval = pthread_mutex_init( mutex, NULL );
68  LeaveCriticalSection( &quarkwinthread_static_initializer_check_lock );
69  return retval;
70 }
71 
73  DWORD rv;
74 
75  if ( *mutex == PTHREAD_MUTEX_INITIALIZER ) pthread_mutex_check_for_static_initialization( mutex );
76  rv = WaitForSingleObject( *mutex, INFINITE );
77  switch (rv) {
78  case WAIT_OBJECT_0:
79  return 0;
80  case WAIT_FAILED:
81  return -1;
82  case WAIT_ABANDONED:
83  return -1;
84  case WAIT_TIMEOUT:
85  return -1;
86  default:
87  return -1;
88  }
89 }
90 
92  DWORD rv;
93 
94  if ( *mutex == PTHREAD_MUTEX_INITIALIZER ) pthread_mutex_check_for_static_initialization( mutex );
95  rv = WaitForSingleObject( *mutex, 0 );
96  switch (rv) {
97  case WAIT_OBJECT_0:
98  return 0;
99  case WAIT_FAILED:
100  return -1;
101  case WAIT_ABANDONED:
102  return -1;
103  case WAIT_TIMEOUT:
104  return -1;
105  default:
106  return -1;
107  }
108 }
109 
111  if (! ReleaseMutex( *mutex ))
112  return -1;
113 
114  return 0;
115 }
116 
118  CloseHandle( *mutex );
119  return 0;
120 }
121 
123  *attr = 1;
124  return 0;
125 }
126 
128  *attr = 0;
129  return 0;
130 }
131 
133  if (*attr != 1)
134  return -1;
135 
136  if (scope != PTHREAD_SCOPE_SYSTEM)
137  return -1;
138 
139  return 0;
140 }
141 
142 void *(*QUARK_realThStart)(void *);
143 
144 /*
145  This function is only called to have a proxy that is compatible with WINAPI.
146  */
147 unsigned WINAPI QUARK_winThStart(void *arg) {
148  QUARK_realThStart( arg );
149  return 0;
150 }
151 
152 QUARK_DLLPORT int QUARK_CDECL pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start) (void *), void *arg) {
153 
154  /* this assumes that the threads call the same function, always; it also assumes there
155  is no race condition while assigning a pointer and using it from within threads
156  (this assumption is fulfilled by creating the new thread in suspended state) */
157  QUARK_realThStart = start;
158 
159  thread->hThread = (HANDLE)_beginthreadex(
160  NULL, /* default security */
161  0, /* stack size: use the size of calling thread */
163  arg,
164  CREATE_SUSPENDED,
165  /*0,*/ /* the thread will run immedietally (rather than get suspended) */
166  &thread->uThId );
167 
168  /* We need to make sure that _beginthreadex() returns to the parent thread first
169  so we can safely fill up the members of the pthread_t structure without possible
170  race conditions. If the new thread is created in supsended state we eliminate
171  the race condition but now we have to resume the new thread. */
172  ResumeThread( thread->hThread );
173 
174  return 0;
175 }
176 
177 QUARK_DLLPORT int QUARK_CDECL pthread_join(pthread_t thread, void **value_ptr) {
178  WaitForSingleObject( thread.hThread, INFINITE );
179  CloseHandle( thread.hThread );
180  return 0;
181 }
182 
184  InitializeCriticalSection( &cond->cs );
185  cond->hSem = CreateSemaphore( NULL, /* no security attributes */
186  0, /* initial count */
187  LONG_MAX, /* maximum count*/
188  NULL ); /* unnamed semaphore */
189  cond->hEvt = CreateEvent( NULL, /* no security attributes */
190  FALSE, /* reset to not-singaled automatically */
191  FALSE, /* set initial status to not-signaled */
192  NULL ); /* unnamed event */
193  cond->waitCount = 0;
194  return 0;
195 }
196 
198  DeleteCriticalSection( &cond->cs );
199  CloseHandle( cond->hSem );
200  CloseHandle( cond->hEvt );
201  return 0;
202 }
203 
205  int last;
206 
207  if ( *mutex == PTHREAD_MUTEX_INITIALIZER ) pthread_mutex_check_for_static_initialization( mutex );
208 
209  /* Avoid race condition on waiting thread counter. */
210  EnterCriticalSection(&cond->cs);
211  cond->waitCount++;
212  LeaveCriticalSection(&cond->cs);
213 
214  /* Releases _atomically_ the mutex and wait on the semaphore until
215  pthread_cond_signal() or pthread_cond_broadcast() are called (by another thread). */
216  SignalObjectAndWait(*mutex, cond->hSem, INFINITE, FALSE);
217 
218  /* Avoid race condition on waiting thread counter. */
219  EnterCriticalSection(&cond->cs);
220  cond->waitCount--; /* this thread doesn't wait any more */
221 
222  /* if this is the last thread to have waited */
223  last = cond->waitCount == 0;
224 
225  LeaveCriticalSection(&cond->cs);
226 
227  /* If this thread is the last waiter thread during this particular broadcast
228  then let all the other threads proceed. */
229  if (last)
230  /* This call ensures that two things happen atomically: signaling the hEvt event and
231  waiting until "mutex" can be acquired. */
232  SignalObjectAndWait(cond->hEvt, *mutex, INFINITE, FALSE);
233  else
234  WaitForSingleObject(*mutex, INFINITE); /* Upon return, this thread has to own "mutex". */
235 
236  return 0;
237 }
238 
240  int more_waiters = 0;
241 
242  /* This is needed to ensure exclusive access to "waitCount" */
243  EnterCriticalSection (&cond->cs);
244 
245  if (cond->waitCount > 0) {
246  /* always are broadcasting - no need for pthread_cond_singal() case */
247  more_waiters = 1;
248  }
249 
250  if (more_waiters) {
251  /* this will wake up all the waiters atomically at once. */
252  ReleaseSemaphore(cond->hSem, cond->waitCount, 0);
253 
254  LeaveCriticalSection(&cond->cs);
255 
256  /* Wait for all the awakened threads to acquire the counting semaphore. */
257  WaitForSingleObject(cond->hEvt, INFINITE);
258  } else
259  LeaveCriticalSection(&cond->cs);
260 
261  return 0;
262 }
263 
265 
267  pthread_conclevel = level;
268  return 0;
269 }