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 294 : struct NaClSimpleLtdService *self,
20 294 : struct NaClSrpcHandlerDesc const *srpc_handlers,
21 294 : int max_cli,
22 294 : NaClThreadIfFactoryFunction thread_factory_fn,
23 294 : void *thread_factory_data) {
24 294 : NaClLog(4, "Entered NaClSimpleLtdServiceCtor\n");
25 294 : 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 294 : if (!NaClMutexCtor(&self->mu)) {
33 0 : NaClLog(4, "NaClSimpleLtdServiceCtor: NaClMutexCtor failed\n");
34 0 : goto mutex_ctor_fail;
35 : }
36 294 : if (!NaClCondVarCtor(&self->cv)) {
37 0 : NaClLog(4, "NaClSimpleLtdServiceCtor: NaClCondVarCtor failed\n");
38 0 : goto condvar_ctor_fail;
39 : }
40 294 : self->max_clients = max_cli;
41 294 : self->num_clients = 0;
42 294 : NACL_VTBL(NaClRefCount, self) =
43 : (struct NaClRefCountVtbl *) &kNaClSimpleLtdServiceVtbl;
44 294 : NaClLog(4, "NaClSimpleLtdServiceCtor: success\n");
45 294 : return 1;
46 :
47 : /* failure cascade, in reverse construction order */
48 : condvar_ctor_fail:
49 0 : NaClMutexDtor(&self->mu);
50 : mutex_ctor_fail:
51 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
52 : base_ctor_fail:
53 0 : return 0;
54 294 : }
55 :
56 0 : void NaClSimpleLtdServiceDtor(struct NaClRefCount *vself) {
57 0 : struct NaClSimpleLtdService *self =
58 : (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 258 : struct NaClSimpleService *vself,
71 258 : struct NaClSimpleServiceConnection **out) {
72 258 : struct NaClSimpleLtdService *self =
73 : (struct NaClSimpleLtdService *) vself;
74 258 : int rv;
75 :
76 258 : NaClXMutexLock(&self->mu);
77 516 : while (self->num_clients >= self->max_clients) {
78 0 : NaClXCondVarWait(&self->cv, &self->mu);
79 0 : }
80 258 : NaClXMutexUnlock(&self->mu);
81 :
82 : /*
83 : * Other threads can only decrement num_clients.
84 : */
85 258 : rv = (*kNaClSimpleServiceVtbl.AcceptConnection)(vself, out);
86 :
87 258 : NaClXMutexLock(&self->mu);
88 258 : self->num_clients++;
89 258 : NaClXMutexUnlock(&self->mu);
90 :
91 258 : return rv;
92 : }
93 :
94 : void NaClSimpleLtdServiceRpcHandler(
95 4 : struct NaClSimpleService *vself,
96 4 : struct NaClSimpleServiceConnection *conn) {
97 4 : struct NaClSimpleLtdService *self =
98 : (struct NaClSimpleLtdService *) vself;
99 :
100 4 : (*kNaClSimpleServiceVtbl.RpcHandler)(vself, conn);
101 4 : NaClXMutexLock(&self->mu);
102 4 : self->num_clients--;
103 4 : NaClXCondVarBroadcast(&self->cv);
104 4 : NaClXMutexUnlock(&self->mu);
105 4 : }
106 :
107 :
108 : struct NaClSimpleServiceVtbl const kNaClSimpleLtdServiceVtbl = {
109 : {
110 : NaClSimpleLtdServiceDtor,
111 : },
112 : NaClSimpleServiceConnectionFactory,
113 : NaClSimpleLtdServiceAcceptConnection,
114 : NaClSimpleServiceAcceptAndSpawnHandler,
115 : NaClSimpleLtdServiceRpcHandler,
116 : };
|