58c4fd72619a1064f2971fe265a0f41d3df8c5b7
[enigma2.git] / lib / base / thread.cpp
1 #include <lib/base/thread.h>
2
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <lib/base/eerror.h>
6
7 void eThread::thread_completed(void *ptr)
8 {
9         eThread *p = (eThread*) ptr;
10         p->m_alive = 0;
11
12                 /* recover state */
13         if (!p->m_state.value())
14         {
15                 p->m_state.up();
16                 ASSERT(p->m_state.value() == 1);
17         }
18
19         p->thread_finished();
20 }
21
22 void *eThread::wrapper(void *ptr)
23 {
24         eThread *p = (eThread*)ptr;
25         pthread_cleanup_push(thread_completed, (void*)p);
26         p->thread();
27         pthread_exit(0);
28         pthread_cleanup_pop(1);
29         return 0;
30 }
31
32 eThread::eThread()
33         : the_thread(0), m_alive(0)
34 {
35 }
36
37 int eThread::runAsync(int prio, int policy)
38 {
39         eDebug("before: %d", m_state.value());
40                 /* the thread might already run. */
41         if (sync())
42                 return -1;
43         
44         eDebug("after: %d", m_state.value());
45         ASSERT(m_state.value() == 1); /* sync postconditions */
46         ASSERT(!m_alive);
47         m_state.down();
48         ASSERT(m_state.value() == 0);
49         
50         m_alive = 1;
51
52                 /* start thread. */
53         pthread_attr_t attr;
54         pthread_attr_init(&attr);
55         
56         if (prio || policy)
57         {
58                 struct sched_param p;
59                 p.__sched_priority=prio;
60                 pthread_attr_setschedpolicy(&attr, policy);
61                 pthread_attr_setschedparam(&attr, &p);
62         }
63         
64         if (pthread_create(&the_thread, &attr, wrapper, this))
65         {
66                 pthread_attr_destroy(&attr);
67                 m_alive = 0;
68                 eDebug("couldn't create new thread");
69                 return -1;
70         }
71         
72         pthread_attr_destroy(&attr);
73         return 0;
74 }                     
75
76 int eThread::run(int prio, int policy)
77 {
78         if (runAsync(prio, policy))
79                 return -1;
80         sync();
81         return 0;
82 }
83
84 eThread::~eThread()
85 {
86         kill();
87 }
88
89 int eThread::sync(void)
90 {
91         int res;
92         int debug_val_before = m_state.value();
93         m_state.down(); /* this might block */
94         res = m_alive;
95         if (m_state.value() != 0)
96                 eFatal("eThread::sync: m_state.value() == %d - was %d before", m_state.value(), debug_val_before);
97         ASSERT(m_state.value() == 0);
98         m_state.up();
99         return res; /* 0: thread is guaranteed not to run. 1: state unknown. */
100 }
101
102 int eThread::sendSignal(int sig)
103 {
104         if (m_alive)
105                 return pthread_kill(the_thread, sig);
106         else
107                 eDebug("send signal to non running thread");
108         return -1;
109 }
110
111 void eThread::kill(bool sendcancel)
112 {
113         if (!the_thread) /* already joined */
114                 return;
115
116         if (sync() && sendcancel)
117         {
118                 eDebug("send cancel to thread");
119                 pthread_cancel(the_thread);
120         }
121         eDebug("thread joined %d", pthread_join(the_thread, 0));
122         the_thread = 0;
123 }
124
125 void eThread::hasStarted()
126 {
127         ASSERT(!m_state.value());
128         m_state.up();
129 }