1 /** 2 * Implementation of support routines for synchronized blocks. 3 * 4 * Copyright: Copyright Digital Mars 2000 - 2011. 5 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 * Authors: Walter Bright, Sean Kelly 7 * Source: $(DRUNTIMESRC rt/_critical_.d) 8 */ 9 10 /* Copyright Digital Mars 2000 - 2011. 11 * Distributed under the Boost Software License, Version 1.0. 12 * (See accompanying file LICENSE or copy at 13 * http://www.boost.org/LICENSE_1_0.txt) 14 */ 15 module rt.critical_; 16 17 nothrow: 18 19 import rt.monitor_, core.atomic; 20 21 extern (C) void _d_critical_init() @nogc nothrow 22 { 23 initMutex(cast(Mutex*)&gcs.mtx); 24 head = &gcs; 25 } 26 27 extern (C) void _d_critical_term() @nogc nothrow 28 { 29 // This function is only ever called by the runtime shutdown code 30 // and therefore is single threaded so the following cast is fine. 31 auto h = cast()head; 32 for (auto p = h; p; p = p.next) 33 destroyMutex(cast(Mutex*)&p.mtx); 34 } 35 36 extern (C) void _d_criticalenter(D_CRITICAL_SECTION* cs) 37 { 38 assert(cs !is null); 39 ensureMutex(cast(shared(D_CRITICAL_SECTION*)) cs); 40 lockMutex(&cs.mtx); 41 } 42 43 extern (C) void _d_criticalenter2(D_CRITICAL_SECTION** pcs) 44 { 45 if (atomicLoad!(MemoryOrder.acq)(*cast(shared) pcs) is null) 46 { 47 lockMutex(cast(Mutex*)&gcs.mtx); 48 if (atomicLoad!(MemoryOrder.raw)(*cast(shared) pcs) is null) 49 { 50 auto cs = new shared D_CRITICAL_SECTION; 51 initMutex(cast(Mutex*)&cs.mtx); 52 atomicStore!(MemoryOrder.rel)(*cast(shared) pcs, cs); 53 } 54 unlockMutex(cast(Mutex*)&gcs.mtx); 55 } 56 lockMutex(&(*pcs).mtx); 57 } 58 59 extern (C) void _d_criticalexit(D_CRITICAL_SECTION* cs) 60 { 61 assert(cs !is null); 62 unlockMutex(&cs.mtx); 63 } 64 65 private: 66 67 shared D_CRITICAL_SECTION* head; 68 shared D_CRITICAL_SECTION gcs; 69 70 struct D_CRITICAL_SECTION 71 { 72 D_CRITICAL_SECTION* next; 73 Mutex mtx; 74 } 75 76 void ensureMutex(shared(D_CRITICAL_SECTION)* cs) 77 { 78 if (atomicLoad!(MemoryOrder.acq)(cs.next) is null) 79 { 80 lockMutex(cast(Mutex*)&gcs.mtx); 81 if (atomicLoad!(MemoryOrder.raw)(cs.next) is null) 82 { 83 initMutex(cast(Mutex*)&cs.mtx); 84 auto ohead = head; 85 head = cs; 86 atomicStore!(MemoryOrder.rel)(cs.next, ohead); 87 } 88 unlockMutex(cast(Mutex*)&gcs.mtx); 89 } 90 }