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