SET(LIBDIR "${LIB_INSTALL_DIR}")
SET(INCLUDEDIR "${PREFIX}/include/${PROJECT_NAME}")
SET(SRCS
- src/argos.c)
+ src/argos.c
+ src/argos_dbus.c
+ src/argos_thread.c
+ src/argos_internal.c
+)
SET(HEADERS
include/argos.h)
AW_OP_CHANGE_TIMEOUT, /**< change watchdog timeout **/
} aw_op_e;
+typedef enum {
+ AW_TYPE_DEFAULT, /**< use systemd or smdl **/
+ AW_TYPE_THREAD, /**< use internal pthread **/
+ AW_TYPE_DBUS, /**< use resourced by dbus **/
+} aw_type_e;
+
/**
* @brief Register watchdog.
*
int aw_register(unsigned int timeout);
/**
+ * @brief Register watchdog with specific type
+ *
+ * @remarks
+ *
+ * @return 0 on success, otherwise a errno-style error value.
+ *
+ */
+int aw_register_ex(aw_type_e type, unsigned int timeout);
+
+/**
* @brief Control watchdog operation.
*
* @since_tizen 2.4
#define _W(fmt, arg...) SLOGW(fmt, ##arg)
#define _E(fmt, arg...) SLOGE(fmt, ##arg)
+/* basic watchdog functions */
int _aw_register(unsigned int timeout);
int _aw_control(aw_op_e op, void *data);
int _aw_notify(void);
+/* for detecting watchdog in internal pthread */
+int aw_register_thread(unsigned int timeout);
+int aw_control_thread(aw_op_e op, void *data);
+int aw_notify_thread(void);
+
+/* for detecting watchdog in resourced using dbus */
+int aw_register_dbus(unsigned int timeout);
+int aw_control_dbus(aw_op_e op, void *data);
+int aw_notify_dbus(void);
+
+void aw_notify_watchdog(void);
+
#endif
#include "common.h"
+static aw_type_e current_type;
+
API int aw_register(unsigned int timeout)
{
- return _aw_register(timeout);
+ return aw_register_ex(AW_TYPE_DEFAULT, timeout);
+}
+
+API int aw_register_ex(aw_type_e type, unsigned int timeout)
+{
+ current_type = type;
+
+ if (type == AW_TYPE_THREAD)
+ return aw_register_thread(timeout);
+ else if (type == AW_TYPE_DBUS)
+ return aw_register_dbus(timeout);
+ else
+ return _aw_register(timeout);
}
API int aw_control(aw_op_e op, void *data)
{
- return _aw_control(op,data);
+ aw_type_e type = current_type;
+
+ if (type == AW_TYPE_THREAD)
+ return aw_control_thread(op,data);
+ else if (type == AW_TYPE_DBUS)
+ return aw_control_dbus(op,data);
+ else
+ return _aw_control(op,data);
}
API int aw_notify(void)
{
- return _aw_notify();
+ aw_type_e type = current_type;
+
+ if (type == AW_TYPE_THREAD)
+ return aw_notify_thread();
+ else if (type == AW_TYPE_DBUS)
+ return aw_notify_dbus();
+ else
+ return _aw_notify();
}
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define RESOURCED_DBUS_BUS_NAME "org.tizen.resourced"
+#define RESOURCED_PATH_PROCESS "/Org/Tizen/ResourceD/Watchdog"
+#define RESOURCED_INTERFACE_PROCESS "org.tizen.resourced.watchdog"
+#define WATCHDOG_START "Start"
+
+static unsigned int dbus_watchdog_timeout=0;
+
+static int aw_send_watchdog(unsigned int timeout)
+{
+ int ret = 0;
+ static GDBusConnection *g_dbus_conn = NULL;
+ GVariant *param = NULL;
+
+ if (!g_dbus_conn)
+ g_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
+
+ if (!g_dbus_conn)
+ return -EINVAL;
+
+ param = g_variant_new("(iu)", getpid(), timeout);
+ g_dbus_connection_call(g_dbus_conn, RESOURCED_DBUS_BUS_NAME,
+ RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS, WATCHDOG_START,
+ param, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+
+ return ret;
+}
+
+int aw_register_dbus(unsigned int timeout)
+{
+ int ret = 0;
+
+ if (timeout == 0)
+ return -EINVAL;
+
+ aw_send_watchdog(timeout);
+ dbus_watchdog_timeout = timeout;
+ return ret;
+}
+
+int aw_control_dbus(aw_op_e op, void *data)
+{
+ int ret = 0;
+ unsigned int* timeout;
+
+ switch(op){
+ case AW_OP_DISABLE:
+ ret = aw_send_watchdog(0);
+ break;
+
+ case AW_OP_ENABLE:
+ ret = aw_send_watchdog(dbus_watchdog_timeout);
+ break;
+
+ case AW_OP_CHANGE_TIMEOUT:
+ timeout = (unsigned int*)(data);
+ if(timeout == NULL){
+ ret = -1;
+ break;
+ }
+ dbus_watchdog_timeout = *timeout;
+ ret = aw_send_watchdog(*timeout);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+int aw_notify_dbus(void)
+{
+ return aw_send_watchdog(dbus_watchdog_timeout);
+}
+
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#define RESOURCED_WATCHDOG_PATH "/Org/Tizen/ResourceD/Process"
+#define RESOURCED_WATCHDOG_INTERFACE "org.tizen.resourced.process"
+#define RESOURCED_WATCHDOG_SIGNAL "ProcWatchdog"
+
+void aw_notify_watchdog(void)
+{
+ GDBusConnection *conn;
+ GError *err = NULL;
+ int pid, pgid;
+ int command = SIGKILL;
+
+ pid = getpid();
+ if (pid < 1)
+ return;
+
+ pgid = getpgid(pid);
+ if (pgid < 1)
+ return;
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (!conn)
+ return;
+
+ _I("detect watchdog %d", pgid);
+ g_dbus_connection_emit_signal(conn, NULL, RESOURCED_WATCHDOG_PATH,
+ RESOURCED_WATCHDOG_INTERFACE, RESOURCED_WATCHDOG_SIGNAL,
+ g_variant_new("(ii)", pgid, command), &err);
+
+ g_dbus_connection_flush_sync (conn, NULL, &err);
+}
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+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;
+}