1 /* $Id: mutex.c,v 1.4 2002/10/29 04:45:38 rex Exp $
4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS POSIX+ Subsystem
6 * FILE: subsys/psx/lib/psxdll/pthread/mutex.c
7 * PURPOSE: Mutex functions
8 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
14 #include <ddk/ntddk.h>
15 #include <sys/types.h>
19 #include <psx/debug.h>
20 #include <psx/pthread.h>
21 #include <psx/errno.h>
22 #include <psx/safeobj.h>
24 int pthread_mutex_init(pthread_mutex_t
*mutex
,
25 const pthread_mutexattr_t
*attr
)
27 struct __mutex
*pmMutex
;
28 struct __mutexattr
*pmaMutexAttrs
;
30 OBJECT_ATTRIBUTES oaMutexAttrs
;
33 /* invalid return buffer */
37 /* object still open */
38 if(__safeobj_validate(*mutex
, __PTHREAD_MUTEX_MAGIC
))
43 /* use default attributes */
44 /* create new mutex object */
45 pmMutex
= (struct __mutex
*)malloc(sizeof(struct __mutex
));
47 /* malloc() failure */
51 /* set the attributes */
53 pmMutex
->type
= PTHREAD_MUTEX_RECURSIVE
;
55 else if(__safeobj_validate(*attr
, __PTHREAD_MUTEX_ATTR_MAGIC
))
57 /* use provided attributes */
58 /* create new mutex object */
59 pmMutex
= (struct __mutex
*)malloc(sizeof(struct __mutex
));
61 /* malloc() failure */
65 /* get the attributes object */
66 pmaMutexAttrs
= (struct __mutexattr
*) *attr
;
68 /* set the attributes */
69 bShared
= (pmaMutexAttrs
->pshared
!= PTHREAD_PROCESS_PRIVATE
);
70 pmMutex
->type
= pmaMutexAttrs
->type
;
75 /* necessary for the mutex to be considered valid later */
76 pmMutex
->signature
= __PTHREAD_MUTEX_MAGIC
;
78 /* creation of the native mutex object */
81 /* initialize generic object attributes */
82 oaMutexAttrs
.Length
= sizeof(OBJECT_ATTRIBUTES
);
83 oaMutexAttrs
.RootDirectory
= NULL
;
84 oaMutexAttrs
.ObjectName
= NULL
;
85 oaMutexAttrs
.Attributes
= 0;
86 oaMutexAttrs
.SecurityDescriptor
= NULL
;
87 oaMutexAttrs
.SecurityQualityOfService
= NULL
;
89 /* process-exclusive mutex */
91 oaMutexAttrs
.Attributes
|= OBJ_EXCLUSIVE
;
93 /* try to create the object */
94 nErrCode
= NtCreateMutant
103 if(!NT_SUCCESS(nErrCode
))
105 /* free the internal mutex object */
108 return (__status_to_errno(nErrCode
));
111 /* return the pointer to the mutex */
112 *mutex
= (pthread_mutex_t
)pmMutex
;
119 int pthread_mutex_destroy(pthread_mutex_t
*mutex
)
121 struct __mutex
*pmMutex
;
123 MUTANT_BASIC_INFORMATION mbiMutexInfo
;
125 /* invalid pointer or pointer to invalid object */
126 if(mutex
== NULL
|| !__safeobj_validate(*mutex
, __PTHREAD_MUTEX_MAGIC
))
131 pmMutex
= (struct __mutex
*)*mutex
;
133 /* query the mutex's status */
134 nErrCode
= NtQueryMutant
137 MutantBasicInformation
,
139 sizeof(MUTANT_BASIC_INFORMATION
),
144 if(!NT_SUCCESS(nErrCode
))
146 return (__status_to_errno(nErrCode
));
149 /* the thread is owned - cannot destroy it */
150 if(mbiMutexInfo
.Count
<= 0)
155 /* try to close the handle */
156 nErrCode
= NtClose(pmMutex
->handle
);
159 if(!NT_SUCCESS(nErrCode
))
161 return (__status_to_errno(nErrCode
));
164 /* free the object, nil the pointer */
173 int pthread_mutex_lock(pthread_mutex_t
*mutex
)
175 struct __mutex
* pmMutex
;
178 /* invalid pointer or pointer to invalid object */
179 if(mutex
== NULL
|| !__safeobj_validate(*mutex
, __PTHREAD_MUTEX_MAGIC
))
182 pmMutex
= (struct __mutex
*)*mutex
;
184 /* decide the behavior from the mutex type */
185 switch(pmMutex
->type
)
187 case PTHREAD_MUTEX_NORMAL
:
189 /* unconditionally try to lock the mutex */
190 /* FIXME? should we "artificially" hang the thread if it's the mutex owner, since
191 NT mutexes always behave recursively? */
194 if(0 /* mutex owner */ == pthread_self() */
)
195 NtDelayExecution(FALSE
, NULL
);
198 nErrCode
= NtWaitForSingleObject(pmMutex
->handle
, FALSE
, NULL
);
202 case PTHREAD_MUTEX_ERRORCHECK
:
204 /* prevent a thread from recursively locking the same mutex */
205 if(0 /* mutex owner */ == pthread_self()) /* FIXME: implement the correct logic */
208 nErrCode
= NtWaitForSingleObject(pmMutex
->handle
, FALSE
, NULL
);
213 case PTHREAD_MUTEX_RECURSIVE
:
215 /* allow recursive locking */
216 /* ASSERT: this is the default behavior for NT */
217 nErrCode
= NtWaitForSingleObject(pmMutex
->handle
, FALSE
, NULL
);
222 /* we should never reach this point */
223 INFO("you should never read this");
227 if(nErrCode
== STATUS_ABANDONED
)
229 FIXME("mutex abandoned, not sure on what to do: should we try to lock the mutex again?");
231 else if(!NT_SUCCESS(nErrCode
))
233 return (__status_to_errno(nErrCode
));
241 int pthread_mutex_trylock(pthread_mutex_t
*mutex
)
243 struct __mutex
* pmMutex
;
245 MUTANT_BASIC_INFORMATION mbiMutexInfo
;
247 /* invalid pointer or pointer to invalid object */
248 if(mutex
== NULL
|| !__safeobj_validate(*mutex
, __PTHREAD_MUTEX_MAGIC
))
251 pmMutex
= (struct __mutex
*)*mutex
;
253 /* query the mutex's status */
254 nErrCode
= NtQueryMutant
257 MutantBasicInformation
,
259 sizeof(MUTANT_BASIC_INFORMATION
),
264 if(!NT_SUCCESS(nErrCode
))
266 return (__status_to_errno(nErrCode
));
269 /* mutex already locked */
270 if(mbiMutexInfo
.Count
<= 0)
273 /* mutex not locked - mutex type attribute doesn't matter */
274 nErrCode
= NtWaitForSingleObject(pmMutex
->handle
, FALSE
, NULL
);
276 if(!NT_SUCCESS(nErrCode
))
278 return (__status_to_errno(nErrCode
));
286 int pthread_mutex_unlock(pthread_mutex_t
*mutex
)
288 struct __mutex
* pmMutex
;
291 /* invalid pointer or pointer to invalid object */
292 if(mutex
== NULL
|| !__safeobj_validate(*mutex
, __PTHREAD_MUTEX_MAGIC
))
295 pmMutex
= (struct __mutex
*)*mutex
;
297 /* try to release the mutex */
298 nErrCode
= NtReleaseMutant(pmMutex
->handle
, NULL
);
301 if(!NT_SUCCESS(nErrCode
))
303 return (__status_to_errno(nErrCode
));
311 /* mutex attributes routines */
313 int pthread_mutexattr_init(pthread_mutexattr_t
*attr
)
315 struct __mutexattr
* pmaMutexAttrs
;
317 /* invalid return pointer */
321 /* allocate internal structure for mutex attributes */
322 pmaMutexAttrs
= (struct __mutexattr
*)malloc(sizeof(struct __mutexattr
));
325 if(pmaMutexAttrs
== 0)
328 /* attribute defaults */
329 pmaMutexAttrs
->pshared
= PTHREAD_PROCESS_PRIVATE
;
330 pmaMutexAttrs
->type
= PTHREAD_MUTEX_DEFAULT
;
332 /* return the pointer to the attributes object */
333 *attr
= (pthread_mutexattr_t
)pmaMutexAttrs
;
340 int pthread_mutexattr_destroy(pthread_mutexattr_t
*attr
)
342 /* invalid pointer or pointer to invalid object */
343 if(attr
== NULL
|| !__safeobj_validate(*attr
, __PTHREAD_MUTEX_ATTR_MAGIC
))
346 /* deallocate internal structure */
354 #define PTHREAD_MUTEXATTR_GET(PATTR,PVAR,FIELD) \
358 !__safeobj_validate(*(PATTR), __PTHREAD_MUTEX_ATTR_MAGIC) \
363 (*(PVAR)) = ((struct __mutexattr *)*(PATTR))->FIELD; \
367 int pthread_mutexattr_getpshared(const pthread_mutexattr_t
*attr
,
370 PTHREAD_MUTEXATTR_GET(attr
, pshared
, pshared
)
373 int pthread_mutexattr_gettype(const pthread_mutexattr_t
*attr
, int *type
)
375 PTHREAD_MUTEXATTR_GET(attr
, type
, type
)
378 int pthread_mutexattr_setpshared(pthread_mutexattr_t
*attr
,
381 /* invalid pointer or pointer to invalid object */
382 if(attr
== NULL
|| !__safeobj_validate(*attr
, __PTHREAD_MUTEX_ATTR_MAGIC
))
388 case PTHREAD_PROCESS_SHARED
: break;
389 case PTHREAD_PROCESS_PRIVATE
: break;
390 default: return (EINVAL
);
393 ((struct __mutexattr
*)*attr
)->pshared
= pshared
;
399 int pthread_mutexattr_settype(pthread_mutexattr_t
*attr
, int type
)
401 /* invalid pointer or pointer to invalid object */
402 if(attr
== NULL
|| !__safeobj_validate(*attr
, __PTHREAD_MUTEX_ATTR_MAGIC
))
408 case PTHREAD_MUTEX_NORMAL
: break;
409 case PTHREAD_MUTEX_ERRORCHECK
: break;
410 case PTHREAD_MUTEX_RECURSIVE
: break;
411 default: return (EINVAL
);
414 ((struct __mutexattr
*)*attr
)->type
= type
;
422 int pthread_mutex_setprioceiling(pthread_mutex_t
*mutex
,
423 int prioceiling
, int *old_ceiling
)
425 TODO("realtime threads not currently implemented");
429 int pthread_mutex_getprioceiling(const pthread_mutex_t
*mutex
,
432 TODO("realtime threads not currently implemented");
436 int pthread_mutexattr_getprotocol(const pthread_mutexattr_t
*attr
,
439 TODO("realtime threads not currently implemented");
443 int pthread_mutexattr_setprotocol(pthread_mutexattr_t
*attr
,
446 TODO("realtime threads not currently implemented");
450 int pthread_mutexattr_setprioceiling(pthread_mutexattr_t
*attr
,
453 TODO("realtime threads not currently implemented");
457 int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t
*attr
,
460 TODO("realtime threads not currently implemented");