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 #include "hal_error.h"
18 #include "hc_log.h"
19
20 #define MAX_THREAD_STACK_SIZE (8 * 1024 * 1024)
21
StaticThreadFunc(void * args)22 void *StaticThreadFunc(void *args)
23 {
24 HcThread *thread = (HcThread*)args;
25 if (thread == NULL) {
26 return NULL;
27 }
28
29 #if defined(SET_THREAD_NAME)
30 int res = pthread_setname_np(pthread_self(), StringGet(&thread->name));
31 if (res != 0) {
32 LOGW("[OS]: pthread_setname_np fail. [Res]: %d", res);
33 }
34 #endif
35
36 if (thread->threadFunc) {
37 thread->threadFunc(args);
38 }
39 thread->threadLock.lock(&thread->threadLock);
40 thread->running = HC_FALSE;
41 thread->threadWaitObj.notifyWithoutLock(&thread->threadWaitObj);
42 thread->threadLock.unlock(&thread->threadLock);
43 return NULL;
44 }
45
Start(struct HcThreadT * thread)46 int Start(struct HcThreadT *thread)
47 {
48 if (thread == NULL) {
49 return HAL_ERR_NULL_PTR;
50 }
51 thread->threadLock.lock(&thread->threadLock);
52 if (thread->running) {
53 thread->threadLock.unlock(&thread->threadLock);
54 return 0;
55 }
56 thread->running = HC_TRUE;
57
58 pthread_attr_t attr;
59 pthread_attr_init(&attr);
60 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
61
62 if (thread->stackSize > 0 && thread->stackSize <= MAX_THREAD_STACK_SIZE) {
63 pthread_attr_setstacksize(&attr, thread->stackSize);
64 }
65
66 LOGI("[OS]: pthread_create enter.");
67 int res = pthread_create(&thread->thread, &attr, StaticThreadFunc, thread);
68 LOGI("[OS]: pthread_create quit. [Res]: %d", res);
69 pthread_attr_destroy(&attr);
70 if (res != 0) {
71 LOGE("[OS]: pthread_create fail. [Res]: %d", res);
72 thread->running = HC_FALSE;
73 }
74 thread->threadLock.unlock(&thread->threadLock);
75 return res;
76 }
77
Join(struct HcThreadT * thread)78 void Join(struct HcThreadT *thread)
79 {
80 if (thread == NULL) {
81 return;
82 }
83
84 if (thread->running) {
85 thread->threadWaitObj.waitWithoutLock(&thread->threadWaitObj);
86 }
87 void *status = NULL;
88 LOGI("[OS]: pthread_join enter.");
89 int res = pthread_join(thread->thread, &status);
90 LOGI("[OS]: pthread_join quit. [Res]: %d", res);
91 if (res != 0) {
92 LOGE("[OS]: pthread_join fail. [Res]: %d", res);
93 }
94 }
95
BizWait(struct HcThreadT * thread)96 void BizWait(struct HcThreadT *thread)
97 {
98 if (thread == NULL) {
99 return;
100 }
101 thread->bizWaitObj.wait(&thread->bizWaitObj);
102 }
103
BizNotify(struct HcThreadT * thread)104 void BizNotify(struct HcThreadT *thread)
105 {
106 if (thread == NULL) {
107 return;
108 }
109 thread->bizWaitObj.notify(&thread->bizWaitObj);
110 }
111
InitThread(HcThread * thread,ThreadFunc func,size_t stackSize,const char * threadName)112 int32_t InitThread(HcThread *thread, ThreadFunc func, size_t stackSize, const char *threadName)
113 {
114 if (thread == NULL) {
115 return -1;
116 }
117
118 thread->threadFunc = func;
119 thread->start = Start;
120 thread->wait = BizWait;
121 thread->notify = BizNotify;
122 thread->join = Join;
123 thread->stackSize = stackSize;
124 thread->running = HC_FALSE;
125 thread->name = CreateString();
126 if (StringSetPointer(&thread->name, threadName) != HC_TRUE) {
127 DeleteString(&thread->name);
128 return -1;
129 }
130
131 int32_t res = InitHcMutex(&thread->threadLock);
132 if (res != 0) {
133 DeleteString(&thread->name);
134 return res;
135 }
136 res = InitHcCond(&thread->threadWaitObj, &thread->threadLock);
137 if (res != 0) {
138 DeleteString(&thread->name);
139 DestroyHcMutex(&thread->threadLock);
140 return res;
141 }
142 res = InitHcCond(&thread->bizWaitObj, NULL);
143 if (res != 0) {
144 DeleteString(&thread->name);
145 DestroyHcMutex(&thread->threadLock);
146 DestroyHcCond(&thread->threadWaitObj);
147 }
148 return res;
149 }
150
DestroyThread(HcThread * thread)151 void DestroyThread(HcThread *thread)
152 {
153 if (thread == NULL) {
154 return;
155 }
156
157 DestroyHcCond(&thread->bizWaitObj);
158 DestroyHcCond(&thread->threadWaitObj);
159 DestroyHcMutex(&thread->threadLock);
160 DeleteString(&thread->name);
161 }
162