00001 /* -*- mode:C++; c-basic-offset:4 -*- 00002 Shore-MT -- Multi-threaded port of the SHORE storage manager 00003 00004 Copyright (c) 2007-2009 00005 Data Intensive Applications and Systems Labaratory (DIAS) 00006 Ecole Polytechnique Federale de Lausanne 00007 00008 All Rights Reserved. 00009 00010 Permission to use, copy, modify and distribute this software and 00011 its documentation is hereby granted, provided that both the 00012 copyright notice and this permission notice appear in all copies of 00013 the software, derivative works or modified versions, and any 00014 portions thereof, and that both notices appear in supporting 00015 documentation. 00016 00017 This code is distributed in the hope that it will be useful, but 00018 WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS 00020 DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER 00021 RESULTING FROM THE USE OF THIS SOFTWARE. 00022 */ 00023 00024 /*<std-header orig-src='shore'> 00025 00026 $Id: sthread_core_pthread.cpp,v 1.11 2012/01/02 17:02:22 nhall Exp $ 00027 00028 SHORE -- Scalable Heterogeneous Object REpository 00029 00030 Copyright (c) 1994-99 Computer Sciences Department, University of 00031 Wisconsin -- Madison 00032 All Rights Reserved. 00033 00034 Permission to use, copy, modify and distribute this software and its 00035 documentation is hereby granted, provided that both the copyright 00036 notice and this permission notice appear in all copies of the 00037 software, derivative works or modified versions, and any portions 00038 thereof, and that both notices appear in supporting documentation. 00039 00040 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY 00041 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS 00042 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND 00043 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 00044 00045 This software was developed with support by the Advanced Research 00046 Project Agency, ARPA order number 018 (formerly 8230), monitored by 00047 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518. 00048 Further funding for this work was provided by DARPA through 00049 Rome Research Laboratory Contract No. F30602-97-2-0247. 00050 00051 */ 00052 00053 #include "w_defines.h" 00054 00055 /* -- do not edit anything above this line -- </std-header>*/ 00056 00057 00058 /* 00059 * NewThreads is Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998 by: 00060 * 00061 * Josef Burger <bolo@cs.wisc.edu> 00062 * Dylan McNamee <dylan@cse.ogi.edu> 00063 * Ed Felten <felten@cs.princeton.edu> 00064 * 00065 * All Rights Reserved. 00066 * 00067 * NewThreads may be freely used as long as credit is given 00068 * to the above authors and the above copyright is maintained. 00069 */ 00070 00071 #include <w.h> 00072 #include "sthread.h" 00073 #include <w_stream.h> 00074 #include <w_pthread.h> 00075 #include "stcore_pthread.h" 00076 00077 // starting function called by every pthread created; core* is the 00078 // argument. Through the core* we get the "real function and arg. 00079 extern "C" void *pthread_core_start(void *_arg); 00080 void *pthread_core_start(void *_arg) 00081 { 00082 sthread_core_t *me = (sthread_core_t *) _arg; 00083 00084 // core is_virgin says the "real" function hasn't started yet 00085 // Unfortunately, we have multiple phases of startup here 00086 me->is_virgin = 0; 00087 (me->start_proc)(me->start_arg); 00088 return 0; 00089 } 00090 00091 00092 int sthread_core_init(sthread_core_t *core, 00093 void (*proc)(void *), void *arg, 00094 unsigned stack_size) 00095 { 00096 int n; 00097 00098 /* Get a life; XXX magic number */ 00099 if (stack_size > 0 && stack_size < 1024) 00100 return -1; 00101 00102 core->is_virgin = 1; 00103 core->start_proc = proc; 00104 core->start_arg = arg; 00105 core->stack_size = stack_size; 00106 00107 if (stack_size > 0) { 00108 /* A real thread :thread id, default attributes, start func, arg */ 00109 n = pthread_create(&core->pthread, NULL, pthread_core_start, core); 00110 if (n == -1) { 00111 w_rc_t e= RC(fcOS); 00112 // EAGAIN: insufficient resources 00113 // Really, there's no way to tell when the system will 00114 // say it's hit the maximum # threads because that depends 00115 // on a variety of resources, and in any case, we don't 00116 // know how much memory will be required for another thread. 00117 cerr << "pthread_create():" << endl << e << endl; 00118 return -1; 00119 } 00120 core->creator = pthread_self(); 00121 } 00122 else { 00123 /* This is the main thread. It runs in the "system" 00124 pthread; no pthread_create is needed. 00125 */ 00126 00127 /* A more elegant solution would be to make a 00128 "fake" stack using the kernel stack origin 00129 and stacksize limit. This could also allow 00130 the main() stack to have a thread-package size limit, 00131 to catch memory hogs in the main thread. */ 00132 00133 /* The system stack is never virgin */ 00134 core->is_virgin = 0; 00135 core->pthread = pthread_self(); 00136 core->creator = core->pthread; // main thread 00137 } 00138 return 0; 00139 } 00140 00141 /* clean up : called on destruction. 00142 * All we do now is join the thread 00143 */ 00144 void sthread_core_exit(sthread_core_t* core, bool &joined) 00145 { 00146 void *join_value=NULL; 00147 if(joined) { 00148 return; 00149 } 00150 00151 /* must wait for the thread and then harvest its thread */ 00152 00153 if (core->stack_size > 0) { 00154 int res = pthread_join(core->pthread, &join_value); 00155 if(res) { 00156 const char *msg=""; 00157 switch(res) { 00158 case EINVAL: 00159 msg = "Not a joinable thread: EINVAL"; 00160 break; 00161 case ESRCH: 00162 msg = "No such thread: ESRCH"; 00163 break; 00164 case EDEADLK: 00165 msg = "Joining with self: EDEADLK"; 00166 break; 00167 default: 00168 break; 00169 } 00170 if(res) { 00171 w_ostrstream o; 00172 o << "sthread_core_exit:" 00173 << " Unexpected result from pthread_join: " 00174 << msg << " core is : "; 00175 00176 o << *core << endl; 00177 00178 W_FATAL_MSG(fcINTERNAL, << o.c_str() << endl); 00179 } 00180 } 00181 /* And the thread is gone */ 00182 } 00183 joined = true; 00184 } 00185 00186 ostream &operator<<(ostream &o, const sthread_core_t &core) 00187 { 00188 o << "core: "; 00189 if (core.stack_size == 0) 00190 W_FORM(o)("[ system thread %#lx creator %#lx ]", 00191 (long) core.pthread, 00192 (long) core.creator 00193 ); 00194 else 00195 W_FORM(o)("[ thread %#lx creator %#lx ] size=%d", 00196 (long) core.pthread, 00197 (long) core.creator, 00198 core.stack_size); 00199 if (core.is_virgin) 00200 o << ", virgin-core"; 00201 return o; 00202 }