/src/rt/critical.c
C | 176 lines | 113 code | 29 blank | 34 comment | 13 complexity | 819be97193b302f76c479144bc8efe81 MD5 | raw file
1/** 2 * Implementation of support routines for synchronized blocks. 3 * 4 * Copyright: Copyright Digital Mars 2000 - 2010. 5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 6 * Authors: Walter Bright, Sean Kelly 7 */ 8 9/* Copyright Digital Mars 2000 - 2010. 10 * Distributed under the Boost Software License, Version 1.0. 11 * (See accompanying file LICENSE_1_0.txt or copy at 12 * http://www.boost.org/LICENSE_1_0.txt) 13 */ 14 15/* ================================= Win32 ============================ */ 16 17#if _WIN32 18 19#include <windows.h> 20 21/****************************************** 22 * Enter/exit critical section. 23 */ 24 25/* We don't initialize critical sections unless we actually need them. 26 * So keep a linked list of the ones we do use, and in the static destructor 27 * code, walk the list and release them. 28 */ 29 30typedef struct D_CRITICAL_SECTION 31{ 32 struct D_CRITICAL_SECTION *next; 33 CRITICAL_SECTION cs; 34} D_CRITICAL_SECTION; 35 36static D_CRITICAL_SECTION *dcs_list; 37static D_CRITICAL_SECTION critical_section; 38static volatile int inited; 39 40void _d_criticalenter(D_CRITICAL_SECTION *dcs) 41{ 42 if (!dcs->next) 43 { 44 EnterCriticalSection(&critical_section.cs); 45 if (!dcs->next) // if, in the meantime, another thread didn't set it 46 { 47 dcs->next = dcs_list; 48 dcs_list = dcs; 49 InitializeCriticalSection(&dcs->cs); 50 } 51 LeaveCriticalSection(&critical_section.cs); 52 } 53 EnterCriticalSection(&dcs->cs); 54} 55 56void _d_criticalexit(D_CRITICAL_SECTION *dcs) 57{ 58 LeaveCriticalSection(&dcs->cs); 59} 60 61void _STI_critical_init() 62{ 63 if (!inited) 64 { InitializeCriticalSection(&critical_section.cs); 65 dcs_list = &critical_section; 66 inited = 1; 67 } 68} 69 70void _STD_critical_term() 71{ 72 if (inited) 73 { inited = 0; 74 while (dcs_list) 75 { 76 DeleteCriticalSection(&dcs_list->cs); 77 dcs_list = dcs_list->next; 78 } 79 } 80} 81 82#endif 83 84/* ================================= linux ============================ */ 85 86#if linux || __APPLE__ || __FreeBSD__ 87 88#include <stdio.h> 89#include <stdlib.h> 90#include <pthread.h> 91 92// PTHREAD_MUTEX_RECURSIVE is the "standard" symbol, 93// while the _NP version is specific to Linux 94#if linux 95# ifndef PTHREAD_MUTEX_RECURSIVE 96# define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP 97# endif 98#endif 99 100/****************************************** 101 * Enter/exit critical section. 102 */ 103 104/* We don't initialize critical sections unless we actually need them. 105 * So keep a linked list of the ones we do use, and in the static destructor 106 * code, walk the list and release them. 107 */ 108 109typedef struct D_CRITICAL_SECTION 110{ 111 struct D_CRITICAL_SECTION *next; 112 pthread_mutex_t cs; 113} D_CRITICAL_SECTION; 114 115static D_CRITICAL_SECTION *dcs_list; 116static D_CRITICAL_SECTION critical_section; 117static pthread_mutexattr_t _criticals_attr; 118 119void _STI_critical_init(void); 120void _STD_critical_term(void); 121 122void _d_criticalenter(D_CRITICAL_SECTION *dcs) 123{ 124 if (!dcs_list) 125 { _STI_critical_init(); 126 atexit(_STD_critical_term); 127 } 128 //printf("_d_criticalenter(dcs = x%x)\n", dcs); 129 if (!dcs->next) 130 { 131 pthread_mutex_lock(&critical_section.cs); 132 if (!dcs->next) // if, in the meantime, another thread didn't set it 133 { 134 dcs->next = dcs_list; 135 dcs_list = dcs; 136 pthread_mutex_init(&dcs->cs, &_criticals_attr); 137 } 138 pthread_mutex_unlock(&critical_section.cs); 139 } 140 pthread_mutex_lock(&dcs->cs); 141} 142 143void _d_criticalexit(D_CRITICAL_SECTION *dcs) 144{ 145 //printf("_d_criticalexit(dcs = x%x)\n", dcs); 146 pthread_mutex_unlock(&dcs->cs); 147} 148 149void _STI_critical_init() 150{ 151 if (!dcs_list) 152 { //printf("_STI_critical_init()\n"); 153 pthread_mutexattr_init(&_criticals_attr); 154 pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE); 155 156 // The global critical section doesn't need to be recursive 157 pthread_mutex_init(&critical_section.cs, 0); 158 dcs_list = &critical_section; 159 } 160} 161 162void _STD_critical_term() 163{ 164 if (dcs_list) 165 { //printf("_STI_critical_term()\n"); 166 while (dcs_list) 167 { 168 //printf("\tlooping... %x\n", dcs_list); 169 pthread_mutex_destroy(&dcs_list->cs); 170 dcs_list = dcs_list->next; 171 } 172 } 173} 174 175#endif 176