1 : /*
2 : * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : /*
8 : * NaCl Server Runtime interruptible condvar, based on nacl_sync
9 : * interface.
10 : */
11 :
12 : #include "native_client/src/include/portability.h"
13 : #include "native_client/src/shared/platform/nacl_interruptible_condvar.h"
14 : #include "native_client/src/shared/platform/nacl_log.h"
15 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
16 :
17 :
18 0 : int NaClIntrCondVarCtor(struct NaClIntrCondVar *cp) {
19 0 : return NaClCondVarCtor(&cp->cv);
20 : }
21 :
22 :
23 0 : void NaClIntrCondVarDtor(struct NaClIntrCondVar *cp) {
24 0 : NaClCondVarDtor(&cp->cv);
25 0 : }
26 :
27 0 : NaClSyncStatus NaClIntrCondVarWait(struct NaClIntrCondVar *cp,
28 0 : struct NaClIntrMutex *mp,
29 0 : struct nacl_abi_timespec const *ts) {
30 0 : NaClSyncStatus rv = NACL_SYNC_INTERNAL_ERROR;
31 0 : NaClXMutexLock(&mp->mu);
32 :
33 0 : if (NACL_INTR_LOCK_HELD != mp->lock_state) {
34 0 : if (NACL_INTR_LOCK_FREE == mp->lock_state) {
35 : /* NACL_INTR_LOCK_FREE - error - you must hold the lock */
36 0 : rv = NACL_SYNC_MUTEX_PERMISSION;
37 :
38 0 : } else {
39 : /* NACL_INTR_LOCK_INTERRUPTED - just fail the request, we assume
40 : * that all objects are interrupted for the same reason
41 : */
42 0 : rv = NACL_SYNC_INTERNAL_ERROR;
43 : }
44 :
45 0 : NaClXMutexUnlock(&mp->mu);
46 0 : return rv;
47 : }
48 :
49 0 : mp->lock_state = NACL_INTR_LOCK_FREE;
50 0 : NaClXCondVarSignal(&mp->cv);
51 : /* wait on the internal condvar according to the call type */
52 0 : if (NULL == ts) {
53 0 : rv = NaClCondVarWait(&cp->cv, &mp->mu);
54 0 : } else {
55 0 : rv = NaClCondVarTimedWaitAbsolute(&cp->cv, &mp->mu, ts);
56 : }
57 :
58 : /*
59 : * When we get here we own mp->mu again so we need to take mp as in
60 : * its implementation. We ignore the timeout because we must own the mutex
61 : * when this function returns.
62 : */
63 0 : while (NACL_INTR_LOCK_HELD == mp->lock_state) {
64 0 : NaClXCondVarWait(&mp->cv, &mp->mu);
65 0 : }
66 :
67 0 : if (NACL_INTR_LOCK_FREE == mp->lock_state) {
68 0 : mp->lock_state = NACL_INTR_LOCK_HELD;
69 0 : }
70 :
71 0 : NaClXMutexUnlock(&mp->mu);
72 0 : return rv;
73 0 : }
74 :
75 0 : NaClSyncStatus NaClIntrCondVarSignal(struct NaClIntrCondVar *cp) {
76 0 : return NaClCondVarSignal(&cp->cv);
77 : }
78 :
79 0 : NaClSyncStatus NaClIntrCondVarBroadcast(struct NaClIntrCondVar *cp) {
80 0 : return NaClCondVarBroadcast(&cp->cv);
81 : }
82 :
83 0 : void NaClIntrCondVarIntr(struct NaClIntrCondVar *cp) {
84 : /*
85 : * NOTE: we assume that mutexes are interrupted first, so we will
86 : * fail to regain ownership of the mutex once the wait for cp->cv is
87 : * completed (see NaClIntrCondVarWait above)
88 : */
89 0 : NaClXCondVarBroadcast(&cp->cv);
90 0 : }
91 :
92 0 : void NaClIntrCondVarReset(struct NaClIntrCondVar *cp) {
93 0 : UNREFERENCED_PARAMETER(cp);
94 : /* nothing to do here - we don't keep status */
95 0 : return;
96 : }
|