sthread_core_pthread.cpp

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 }

Generated on Mon Jan 2 15:13:57 2012 for Shore Storage Manager by  doxygen 1.4.7