/* * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "common.h" #include #include #include #include #include static pthread_mutex_t aw_mutex; static pthread_cond_t aw_cond; static unsigned int thread_timeout; static bool thread_watchdog_running; static void *aw_thread_main(void * data) { int ret; struct timespec ts; while (1) { pthread_mutex_lock(&aw_mutex); memset(&ts, 0, sizeof(ts)); clock_gettime(CLOCK_MONOTONIC, &ts); _D("current time %lld.%.9ld", (long long)ts.tv_sec, ts.tv_nsec); ts.tv_sec += thread_timeout; _D("wait time %lld.%.9ld", (long long)ts.tv_sec, ts.tv_nsec); ret = pthread_cond_timedwait(&aw_cond, &aw_mutex, &ts); _D("wakeup : %d", ret); if (ret == ETIMEDOUT && thread_watchdog_running) { aw_notify_watchdog(); break; } pthread_mutex_unlock(&aw_mutex); } return NULL; } int aw_register_thread(unsigned int timeout) { int ret = 0; pthread_t pth = 0; pthread_condattr_t cattr; if (timeout == 0) return -EINVAL; pthread_mutex_init(&aw_mutex, NULL); pthread_condattr_init(&cattr); pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC); pthread_cond_init(&aw_cond, &cattr); thread_timeout = timeout; thread_watchdog_running = true; _D("create watchdog thread with %d", thread_timeout); ret = pthread_create(&pth, NULL, &aw_thread_main, (void *)NULL); if (ret) return ret; pthread_detach(pth); return ret; } int aw_control_thread(aw_op_e op, void *data) { int ret = 0; unsigned int* timeout; pthread_mutex_lock(&aw_mutex); switch(op){ case AW_OP_DISABLE: thread_watchdog_running = false; break; case AW_OP_ENABLE: thread_watchdog_running = true; break; case AW_OP_CHANGE_TIMEOUT: timeout = (unsigned int*)(data); if(timeout == NULL){ ret = -1; break; } thread_timeout = *timeout; break; default: ret = -1; break; } pthread_mutex_unlock(&aw_mutex); return ret; } int aw_notify_thread(void) { int ret; ret = pthread_mutex_trylock(&aw_mutex); if (ret == 0) { _D("send notify"); pthread_cond_signal(&aw_cond); pthread_mutex_unlock(&aw_mutex); } return ret; }