1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk1/threadsgi.cpp
3 // Purpose:     wxThread (SGI) Implementation
4 // Author:      Original from Wolfram Gloger/Guilhem Lavaux
5 // Modified by:
6 // Created:     04/22/98
7 // RCS-ID:      $Id: threadsgi.cpp 40943 2006-08-31 19:31:43Z ABX $
8 // Copyright:   (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998)
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14 
15 #include "wx/thread.h"
16 
17 #ifndef WX_PRECOMP
18     #include "wx/log.h"
19     #include "wx/utils.h"
20     #include "wx/module.h"
21 #endif
22 
23 #include <stdio.h>
24 #include <unistd.h>
25 
26 #include <signal.h>
27 #include <sys/wait.h>
28 #include <sys/prctl.h>
29 
30 #include "gdk/gdk.h"
31 #include "gtk/gtk.h"
32 
33 enum thread_state
34 {
35   STATE_IDLE = 0,
36   STATE_RUNNING,
37   STATE_CANCELED,
38   STATE_EXITED
39 };
40 
41 /////////////////////////////////////////////////////////////////////////////
42 // Static variables
43 /////////////////////////////////////////////////////////////////////////////
44 
45 static int p_mainid;
46 wxMutex *wxMainMutex;
47 
48 #include "threadgui.inc"
49 
50 /////////////////////////////////////////////////////////////////////////////
51 // Unix implementations (SGI threads)
52 /////////////////////////////////////////////////////////////////////////////
53 
54 class wxMutexInternal {
55 public:
56   abilock_t p_mutex;
57 };
58 
wxMutex()59 wxMutex::wxMutex()
60 {
61   m_locked = 0;
62   p_internal = new wxMutexInternal;
63   init_lock(&(p_internal->p_mutex));
64 }
65 
~wxMutex()66 wxMutex::~wxMutex()
67 {
68   if (m_locked > 0)
69     wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked );
70   delete p_internal;
71 }
72 
Lock()73 wxMutexError wxMutex::Lock()
74 {
75   spin_lock(&(p_internal->p_mutex));
76   m_locked++;
77   return wxMUTEX_NO_ERROR;
78 }
79 
TryLock()80 wxMutexError wxMutex::TryLock()
81 {
82   if (acquire_lock(&(p_internal->p_mutex)) != 0)
83     return wxMUTEX_BUSY;
84   m_locked++;
85   return wxMUTEX_NO_ERROR;
86 }
87 
Unlock()88 wxMutexError wxMutex::Unlock()
89 {
90   if (m_locked == 0)
91     return wxMUTEX_UNLOCKED;
92   release_lock(&(p_internal->p_mutex));
93   m_locked--;
94   return wxMUTEX_NO_ERROR;
95 }
96 
97 // GL: Don't know how it works on SGI. Wolfram ?
98 
wxCondition()99 wxCondition::wxCondition() {}
~wxCondition()100 wxCondition::~wxCondition() {}
Wait(wxMutex & WXUNUSED (mutex))101 int wxCondition::Wait(wxMutex& WXUNUSED(mutex)) { return 0;}
Wait(wxMutex & WXUNUSED (mutex),unsigned long WXUNUSED (sec),unsigned long WXUNUSED (nsec))102 int wxCondition::Wait(wxMutex& WXUNUSED(mutex), unsigned long WXUNUSED(sec),
103                       unsigned long WXUNUSED(nsec)) { return 0; }
Signal()104 int wxCondition::Signal() { return 0; }
Broadcast()105 int wxCondition::Broadcast() { return 0; }
106 
107 class
108 wxThreadPrivate {
109 public:
wxThreadPrivate()110   wxThreadPrivate() { thread_id = 0; state = STATE_IDLE; }
~wxThreadPrivate()111   ~wxThreadPrivate() {}
112   static void SprocStart(void *ptr);
113   static void SignalHandler(int sig);
114 public:
115   int state, thread_id;
116   void* exit_status;
117 };
118 
SprocStart(void * ptr)119 void wxThreadPrivate::SprocStart(void *ptr)
120 {
121   void* status;
122 
123   wxThread *thr = (wxThread *)ptr;
124 
125   thr->p_internal->thread_id = getpid();
126   thr->p_internal->exit_status = 0;
127   status = thr->Entry();
128   thr->Exit(status);
129 }
130 
Exit(void * status)131 void wxThread::Exit(void* status)
132 {
133   wxThread* ptr = this;
134   THREAD_SEND_EXIT_MSG(ptr);
135   p_internal->state = STATE_EXITED;
136   p_internal->exit_status = status;
137   _exit(0);
138 }
139 
Create()140 wxThreadError wxThread::Create()
141 {
142   if (p_internal->state != STATE_IDLE)
143     return wxTHREAD_RUNNING;
144   p_internal->state = STATE_RUNNING;
145   if (sproc(p_internal->SprocStart, PR_SALL, this) < 0) {
146     p_internal->state = STATE_IDLE;
147     return wxTHREAD_NO_RESOURCE;
148   }
149   return wxTHREAD_NO_ERROR;
150 }
151 
Destroy()152 wxThreadError wxThread::Destroy()
153 {
154   if (p_internal->state == STATE_RUNNING)
155     p_internal->state = STATE_CANCELED;
156 
157   return wxTHREAD_NO_ERROR;
158 }
159 
Pause()160 wxThreadError wxThread::Pause()
161 {
162   return wxTHREAD_NO_ERROR;
163 }
164 
Resume()165 wxThreadError wxThread::Resume()
166 {
167   return wxTHREAD_NO_ERROR;
168 }
169 
Join()170 void *wxThread::Join()
171 {
172   if (p_internal->state != STATE_IDLE) {
173     bool do_unlock = wxThread::IsMain();
174     int stat;
175 
176     if (do_unlock)
177       wxMainMutex->Unlock();
178     waitpid(p_internal->thread_id, &stat, 0);
179     if (do_unlock)
180       wxMainMutex->Lock();
181     if (!WIFEXITED(stat) && !WIFSIGNALED(stat))
182       return 0;
183     p_internal->state = STATE_IDLE;
184     return p_internal->exit_status;
185   }
186   return 0;
187 }
188 
GetID() const189 unsigned long wxThread::GetID() const
190 {
191   return (unsigned long)p_internal->thread_id;
192 }
193 
TestDestroy()194 void wxThread::TestDestroy()
195 {
196   if (p_internal->state == STATE_CANCELED) {
197     p_internal->exit_status = 0;
198     _exit(0);
199   }
200 }
201 
SetPriority(int prio)202 void wxThread::SetPriority(int prio)
203 {
204 }
205 
GetPriority() const206 int wxThread::GetPriority() const
207 {
208     return 0;
209 }
210 
IsMain()211 bool wxThread::IsMain()
212 {
213   return (int)getpid() == main_id;
214 }
215 
IsAlive() const216 bool wxThread::IsAlive() const
217 {
218   return (p_internal->state == STATE_RUNNING);
219 }
220 
IsRunning() const221 bool wxThread::IsRunning() const
222 {
223   return (p_internal->state == STATE_RUNNING);
224 }
225 
wxThread()226 wxThread::wxThread()
227 {
228   p_internal = new wxThreadPrivate();
229 }
230 
~wxThread()231 wxThread::~wxThread()
232 {
233   Cancel();
234   Join();
235   delete p_internal;
236 }
237 
238 // The default callback just joins the thread and throws away the result.
OnExit()239 void wxThread::OnExit()
240 {
241   Join();
242 }
243 
244 // Global initialization
245 
246 class wxThreadModule : public wxModule
247 {
248 public:
249     virtual bool OnInit();
250     virtual void OnExit();
251 
252 private:
253     DECLARE_DYNAMIC_CLASS(wxThreadModule)
254 };
255 
IMPLEMENT_DYNAMIC_CLASS(wxThreadModule,wxModule)256 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
257 
258 bool wxThreadModule::OnInit()
259 {
260     wxMainMutex = new wxMutex();
261     wxThreadGuiInit();
262     p_mainid = (int)getpid();
263     wxMainMutex->Lock();
264     return true;
265 }
266 
OnExit()267 void wxThreadModule::OnExit()
268 {
269     wxMainMutex->Unlock();
270     wxThreadGuiExit();
271     delete wxMainMutex;
272 }
273