1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hc_thread.h"
17
18 #define MAX_THREAD_STACK_SIZE (8 * 1024 * 1024)
19
StaticThreadFunc(void * args)20 void *StaticThreadFunc(void *args)
21 {
22 HcThread *thread = (HcThread*)args;
23 if (thread == NULL) {
24 return NULL;
25 }
26
27 (void)pthread_setname_np(pthread_self(), StringGet(&thread->name));
28
29 if (thread->threadFunc) {
30 thread->threadFunc(args);
31 }
32 thread->threadLock.lock(&thread->threadLock);
33 thread->running = HC_FALSE;
34 thread->threadWaitObj.notifyWithoutLock(&thread->threadWaitObj);
35 thread->threadLock.unlock(&thread->threadLock);
36 return NULL;
37 }
38
Start(struct HcThreadT * thread)39 int Start(struct HcThreadT *thread)
40 {
41 if (thread == NULL) {
42 return -1;
43 }
44 thread->threadLock.lock(&thread->threadLock);
45 if (thread->running) {
46 thread->threadLock.unlock(&thread->threadLock);
47 return 0;
48 }
49 thread->running = HC_TRUE;
50
51 pthread_attr_t attr;
52 pthread_attr_init(&attr);
53 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
54
55 if (thread->stackSize > 0 && thread->stackSize <= MAX_THREAD_STACK_SIZE) {
56 pthread_attr_setstacksize(&attr, thread->stackSize);
57 }
58
59 int result = pthread_create(&thread->thread, &attr, StaticThreadFunc, thread);
60 pthread_attr_destroy(&attr);
61 if (result != 0) {
62 thread->running = HC_FALSE;
63 }
64 thread->threadLock.unlock(&thread->threadLock);
65 return result;
66 }
67
Join(struct HcThreadT * thread)68 void Join(struct HcThreadT *thread)
69 {
70 if (thread == NULL) {
71 return;
72 }
73
74 if (thread->running) {
75 thread->threadWaitObj.waitWithoutLock(&thread->threadWaitObj);
76 }
77 void *status = NULL;
78 pthread_join(thread->thread, &status);
79 }
80
BizWait(struct HcThreadT * thread)81 void BizWait(struct HcThreadT *thread)
82 {
83 if (thread == NULL) {
84 return;
85 }
86 thread->bizWaitObj.wait(&thread->bizWaitObj);
87 }
88
BizNotify(struct HcThreadT * thread)89 void BizNotify(struct HcThreadT *thread)
90 {
91 if (thread == NULL) {
92 return;
93 }
94 thread->bizWaitObj.notify(&thread->bizWaitObj);
95 }
96
InitThread(HcThread * thread,ThreadFunc func,size_t stackSize,const char * threadName)97 int32_t InitThread(HcThread *thread, ThreadFunc func, size_t stackSize, const char *threadName)
98 {
99 if (thread == NULL) {
100 return -1;
101 }
102
103 thread->threadFunc = func;
104 thread->start = Start;
105 thread->wait = BizWait;
106 thread->notify = BizNotify;
107 thread->join = Join;
108 thread->stackSize = stackSize;
109 thread->running = HC_FALSE;
110 thread->name = CreateString();
111 if (StringSetPointer(&thread->name, threadName) != HC_TRUE) {
112 return -1;
113 }
114
115 int32_t res = InitHcMutex(&thread->threadLock);
116 if (res != 0) {
117 DeleteString(&thread->name);
118 return res;
119 }
120 res = InitHcCond(&thread->threadWaitObj, &thread->threadLock);
121 if (res != 0) {
122 DeleteString(&thread->name);
123 DestroyHcMutex(&thread->threadLock);
124 return res;
125 }
126 res = InitHcCond(&thread->bizWaitObj, NULL);
127 if (res != 0) {
128 DeleteString(&thread->name);
129 DestroyHcMutex(&thread->threadLock);
130 DestroyHcCond(&thread->threadWaitObj);
131 }
132 return res;
133 }
134
DestroyThread(HcThread * thread)135 void DestroyThread(HcThread *thread)
136 {
137 if (thread == NULL) {
138 return;
139 }
140
141 DestroyHcCond(&thread->bizWaitObj);
142 DestroyHcCond(&thread->threadWaitObj);
143 DestroyHcMutex(&thread->threadLock);
144 DeleteString(&thread->name);
145 }
146