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 : #include "native_client/src/trusted/simple_service/nacl_simple_ltd_service.h"
8 :
9 : #include "native_client/src/include/nacl_compiler_annotations.h"
10 :
11 : #include "native_client/src/shared/platform/nacl_check.h"
12 : #include "native_client/src/shared/platform/nacl_log.h"
13 : #include "native_client/src/shared/platform/nacl_sync.h"
14 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
15 : #include "native_client/src/shared/platform/nacl_threads.h"
16 : #include "native_client/src/shared/srpc/nacl_srpc.h"
17 :
18 : int NaClSimpleLtdServiceCtor(
19 : struct NaClSimpleLtdService *self,
20 : struct NaClSrpcHandlerDesc const *srpc_handlers,
21 : int max_cli,
22 : NaClThreadIfFactoryFunction thread_factory_fn,
23 19 : void *thread_factory_data) {
24 19 : NaClLog(4, "Entered NaClSimpleLtdServiceCtor\n");
25 19 : if (!NaClSimpleServiceCtor((struct NaClSimpleService *) self,
26 : srpc_handlers,
27 : thread_factory_fn,
28 : thread_factory_data)) {
29 0 : NaClLog(4, "NaClSimpleServiceCtor failed\n");
30 0 : goto base_ctor_fail;
31 : }
32 19 : if (!NaClMutexCtor(&self->mu)) {
33 0 : NaClLog(4, "NaClSimpleLtdServiceCtor: NaClMutexCtor failed\n");
34 0 : goto mutex_ctor_fail;
35 : }
36 19 : if (!NaClCondVarCtor(&self->cv)) {
37 0 : NaClLog(4, "NaClSimpleLtdServiceCtor: NaClCondVarCtor failed\n");
38 0 : goto condvar_ctor_fail;
39 : }
40 19 : self->max_clients = max_cli;
41 19 : self->num_clients = 0;
42 19 : NACL_VTBL(NaClRefCount, self) =
43 : (struct NaClRefCountVtbl *) &kNaClSimpleLtdServiceVtbl;
44 19 : NaClLog(4, "NaClSimpleLtdServiceCtor: success\n");
45 19 : return 1;
46 :
47 : /* failure cascade, in reverse construction order */
48 0 : condvar_ctor_fail:
49 0 : NaClMutexDtor(&self->mu);
50 0 : mutex_ctor_fail:
51 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
52 0 : base_ctor_fail:
53 0 : return 0;
54 : }
55 :
56 0 : void NaClSimpleLtdServiceDtor(struct NaClRefCount *vself) {
57 : struct NaClSimpleLtdService *self =
58 0 : (struct NaClSimpleLtdService *) vself;
59 :
60 0 : CHECK(0 == self->num_clients);
61 0 : NaClCondVarDtor(&self->cv);
62 0 : NaClMutexDtor(&self->mu);
63 0 : NACL_VTBL(NaClRefCount, self) =
64 : (struct NaClRefCountVtbl *) &kNaClSimpleServiceVtbl;
65 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
66 0 : }
67 :
68 :
69 : int NaClSimpleLtdServiceAcceptConnection(
70 : struct NaClSimpleService *vself,
71 3 : struct NaClSimpleServiceConnection **out) {
72 : struct NaClSimpleLtdService *self =
73 3 : (struct NaClSimpleLtdService *) vself;
74 : int rv;
75 :
76 3 : NaClXMutexLock(&self->mu);
77 6 : while (self->num_clients >= self->max_clients) {
78 0 : NaClXCondVarWait(&self->cv, &self->mu);
79 : }
80 3 : NaClXMutexUnlock(&self->mu);
81 :
82 : /*
83 : * Other threads can only decrement num_clients.
84 : */
85 3 : rv = (*kNaClSimpleServiceVtbl.AcceptConnection)(vself, out);
86 :
87 0 : NaClXMutexLock(&self->mu);
88 0 : self->num_clients++;
89 0 : NaClXMutexUnlock(&self->mu);
90 :
91 0 : return rv;
92 : }
93 :
94 : void NaClSimpleLtdServiceRpcHandler(
95 : struct NaClSimpleService *vself,
96 0 : struct NaClSimpleServiceConnection *conn) {
97 : struct NaClSimpleLtdService *self =
98 0 : (struct NaClSimpleLtdService *) vself;
99 :
100 0 : (*kNaClSimpleServiceVtbl.RpcHandler)(vself, conn);
101 0 : NaClXMutexLock(&self->mu);
102 0 : self->num_clients--;
103 0 : NaClXCondVarBroadcast(&self->cv);
104 0 : NaClXMutexUnlock(&self->mu);
105 0 : }
106 :
107 :
108 : struct NaClSimpleServiceVtbl const kNaClSimpleLtdServiceVtbl = {
109 : {
110 : NaClSimpleLtdServiceDtor,
111 : },
112 : NaClSimpleServiceConnectionFactory,
113 : NaClSimpleLtdServiceAcceptConnection,
114 : NaClSimpleServiceAcceptAndSpawnHandler,
115 : NaClSimpleLtdServiceRpcHandler,
116 : };
|