1 : /*
2 : * Copyright (c) 2012 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/nacl_base/nacl_refcount.h"
8 :
9 : #include "native_client/src/shared/platform/nacl_log.h"
10 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
11 :
12 5072 : int NaClRefCountCtor(struct NaClRefCount *self) {
13 5072 : NaClLog(4, "NaClRefCountCtor(0x%08"NACL_PRIxPTR").\n", (uintptr_t) self);
14 5072 : self->ref_count = 1;
15 5072 : self->vtbl = (struct NaClRefCountVtbl *) NULL;
16 5072 : if (NaClFastMutexCtor(&self->mu)) {
17 5072 : self->vtbl = &kNaClRefCountVtbl;
18 5072 : return 1;
19 : }
20 0 : return 0;
21 : }
22 :
23 1192 : static void NaClRefCountDtor(struct NaClRefCount *self) {
24 1192 : NaClLog(4, "NaClRefCountDtor(0x%08"NACL_PRIxPTR"), refcount %"NACL_PRIuS
25 : ", destroying.\n",
26 : (uintptr_t) self,
27 : self->ref_count);
28 : /*
29 : * NB: refcount could be non-zero. Here's why: if a subclass's Ctor
30 : * fails, it will have already run NaClRefCountCtor and have
31 : * initialized the mutex and set the ref_count to 1. Because Unref
32 : * would free memory and Ctors aren't factories, the subclass Ctor
33 : * cannot just invoke NaClRefCountUnref; instead, it must directly
34 : * invoke the base class Dtor.
35 : *
36 : * We do, however, expect the ref_count to be either 0 or 1.
37 : */
38 1192 : switch (self->ref_count) {
39 : case 0:
40 1192 : break;
41 : case 1:
42 0 : NaClLog(LOG_WARNING,
43 : ("NaClRefCountDtor invoked on a generic refcounted"
44 : " object at 0x%08"NACL_PRIxPTR" with refcount 1."
45 : " This legitimately occurs only during subclass"
46 : " ctor failures.\n"),
47 : (uintptr_t) self);
48 0 : break;
49 : default:
50 0 : NaClLog(LOG_FATAL,
51 : ("NaClRefCountDtor invoked on a generic refcounted"
52 : " object at 0x%08"NACL_PRIxPTR" with non-zero"
53 : " reference count (%"NACL_PRIuS")\n"),
54 : (uintptr_t) self,
55 : self->ref_count);
56 : }
57 :
58 1192 : NaClFastMutexDtor(&self->mu);
59 1192 : self->vtbl = (struct NaClRefCountVtbl const *) NULL;
60 1192 : }
61 :
62 : struct NaClRefCountVtbl const kNaClRefCountVtbl = {
63 : NaClRefCountDtor,
64 : };
65 :
66 86256 : struct NaClRefCount *NaClRefCountRef(struct NaClRefCount *nrcp) {
67 86256 : NaClLog(4, "NaClRefCountRef(0x%08"NACL_PRIxPTR").\n",
68 : (uintptr_t) nrcp);
69 86252 : NaClFastMutexLock(&nrcp->mu);
70 86260 : if (0 == ++nrcp->ref_count) {
71 0 : NaClLog(LOG_FATAL, "NaClRefCountRef integer overflow\n");
72 : }
73 86260 : NaClFastMutexUnlock(&nrcp->mu);
74 86261 : return nrcp;
75 : }
76 :
77 84586 : void NaClRefCountUnref(struct NaClRefCount *nrcp) {
78 : int destroy;
79 :
80 84586 : NaClLog(4, "NaClRefCountUnref(0x%08"NACL_PRIxPTR").\n",
81 : (uintptr_t) nrcp);
82 84586 : NaClFastMutexLock(&nrcp->mu);
83 84589 : if (0 == nrcp->ref_count) {
84 0 : NaClLog(LOG_FATAL,
85 : ("NaClRefCountUnref on 0x%08"NACL_PRIxPTR
86 : ", refcount already zero!\n"),
87 : (uintptr_t) nrcp);
88 : }
89 84589 : destroy = (0 == --nrcp->ref_count);
90 84589 : NaClFastMutexUnlock(&nrcp->mu);
91 84590 : if (destroy) {
92 1192 : (*nrcp->vtbl->Dtor)(nrcp);
93 1192 : free(nrcp);
94 : }
95 84590 : }
96 :
97 299 : void NaClRefCountSafeUnref(struct NaClRefCount *nrcp) {
98 299 : NaClLog(4, "NaClRefCountSafeUnref(0x%08"NACL_PRIxPTR").\n",
99 : (uintptr_t) nrcp);
100 299 : if (NULL == nrcp) {
101 572 : return;
102 : }
103 26 : NaClRefCountUnref(nrcp);
104 : }
105 :
106 3583 : void NaClRefCountLock(struct NaClRefCount *nrcp) {
107 3583 : NaClFastMutexLock(&nrcp->mu);
108 3583 : }
109 :
110 3583 : void NaClRefCountUnlock(struct NaClRefCount *nrcp) {
111 3583 : NaClFastMutexUnlock(&nrcp->mu);
112 3583 : }
|