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