void Mutex_Lock(Mutex mutex, const char *reason) { if (WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0) { /* Got mutex */ multi_debug("%s: lock acquired", reason); } else { multi_debug("%s: waiting on lock", reason); WaitForSingleObject(mutex, INFINITE); multi_debug("lock relinquished"); } }
static void ResetManualEvent(ManualEvent ME) { multi_debug("reset manual event locks"); #if GLIB_CHECK_VERSION (2,32,0) g_mutex_lock(&condMutex); ME->signalled = FALSE; g_mutex_unlock(&condMutex); #else g_mutex_lock(condMutex); ME->signalled = FALSE; g_mutex_unlock(condMutex); #endif multi_debug("reset manual event unlocks"); }
static void MT_CreateThreads(void) { unsigned int i; multi_debug("CreateThreads()"); td.result = 0; td.closingThreads = FALSE; for (i = 0; i < td.numThreads; i++) { int *pID = (int *) malloc(sizeof(int)); *pID = i; #ifdef GLIB_THREADS #if GLIB_CHECK_VERSION (2,32,0) if (!g_thread_try_new("Worker", MT_WorkerThreadFunction, pID, NULL)) #else if (!g_thread_create(MT_WorkerThreadFunction, pID, FALSE, NULL)) #endif #else if (_beginthread(MT_WorkerThreadFunction, 0, pID) == 0) #endif printf("Failed to create thread\n"); } td.addedTasks = td.numThreads; /* Wait for all the threads to be created (timeout after 1 second) */ if (MT_WaitForTasks(WaitingForThreads, 1000, FALSE) != (int) td.numThreads) g_print("Error creating threads!\n"); }
// Special loop that runs even if the watch is not on // We can't rely on pulse_register_timer etc since they aren't running if // the screen isn't on. // pulse_get_millis doesn't update, and the clock runs so slow that per min is // about as good as it gets. // Screen cannot be used. void mode_btlostphone_apploop(void) { multi_debug("mode_btlostphone_apploop\n"); // multi_debug("%i > %i\n", pulse_get_millis(), mode_btlostphone_millis); // ALARM if we have passed our timeout if (multiTimeNow.tm_min != mode_btlostphone_min) { multi_debug("vibe!\n"); // schedule next "alarm" mode_btlostphone_min = multiTimeNow.tm_min; // Buzz pulse_vibe_on(); pulse_mdelay(1000); // should notice this... pulse_vibe_off(); } }
static void SetManualEvent(ManualEvent ME) { multi_debug("reset manual event locks"); #if GLIB_CHECK_VERSION (2,32,0) g_mutex_lock(&condMutex); ME->signalled = TRUE; g_cond_broadcast(&ME->cond); g_mutex_unlock(&condMutex); #else g_mutex_lock(condMutex); ME->signalled = TRUE; g_cond_broadcast(ME->cond); g_mutex_unlock(condMutex); #endif multi_debug("reset manual event unlocks"); }
void mode_demo_init() { multi_debug("init\n"); multiMyWatchFaceName = "mode_demo"; multiLoopTimeMS = 1000; // 1 second, since 200ms is too spammy in the demo multiButtonDownLongPressTimeMS = 400; // just under half a second printf("MODEINIT\nThe display is not really available...\n"); // Would normally not pause here! pulse_mdelay(2000); }
void mode_displaysleep_draw_digit(int iPosition, int iDigit) { multi_debug("digit %i %i\n", iPosition, iDigit); if(modeDisplaysleepCurrentlyDisplayed[iPosition] != iDigit) { modeDisplaysleepCurrentlyDisplayed[iPosition] = iDigit; pulse_draw_image(modeDisplaySleepWatchDigits[iDigit], SCREEN_WIDTH - 12, 50 + (7 * iPosition)); } }
static void Mutex_Release(Mutex mutex) { #ifdef DEBUG_MULTITHREADED multi_debug("Releasing lock"); #endif #if GLIB_CHECK_VERSION (2,32,0) g_mutex_unlock(&mutex); #else g_mutex_unlock(mutex); #endif }
int MT_WaitForTasks(gboolean(*pCallback) (gpointer), int callbackTime, int autosave) { int callbackLoops = callbackTime / UI_UPDATETIME; int waits = 0; int polltime = callbackLoops ? UI_UPDATETIME : callbackTime; guint as_source = 0; /* Set total tasks to wait for */ td.totalTasks = td.addedTasks; #if USE_GTK GTKSuspendInput(); #endif if (autosave) as_source = g_timeout_add(nAutoSaveTime * 60000, save_autosave, NULL); multi_debug("Waiting for all tasks"); while (!WaitForAllTasks(polltime)) { waits++; if (pCallback && waits >= callbackLoops) { waits = 0; pCallback(NULL); } ProcessEvents(); } if (autosave) { g_source_remove(as_source); save_autosave(NULL); } multi_debug("Done waiting for all tasks"); td.doneTasks = td.addedTasks = 0; td.totalTasks = -1; #if USE_GTK GTKResumeInput(); #endif return td.result; }
// This is called regularly to stop the watch "going to sleep"; all we // want to do here is cancel our existing timer and create a new one void mode_displaysleep_update_power_down(int iPowerDownMS) { multi_debug("mode_displaysleep_update_power_down %i\n", iPowerDownMS); // Ensure our own personal "active" loop is cancelled pulse_cancel_timer(&modeDisplaysleepingTimerID); assert(modeDisplaysleepingTimerID == -1); pulse_cancel_timer(&modeDisplaysleepPowerDownTimerID); // pulse assert(modeDisplaysleepPowerDownTimerID == -1); modeDisplaysleepPowerDownTimerID = pulse_register_timer(iPowerDownMS, &mode_displaysleep_power_down, 0); // pulse assert(modeDisplaysleepPowerDownTimerID != -1); }
static void Mutex_Lock(Mutex mutex, const char *reason) { #ifdef DEBUG_MULTITHREADED multi_debug(reason); #else (void) reason; #endif #if GLIB_CHECK_VERSION (2,32,0) g_mutex_lock(&mutex); #else g_mutex_lock(mutex); #endif }
static void WaitForManualEvent(ManualEvent ME) { #if GLIB_CHECK_VERSION (2,32,0) gint64 end_time; #else GTimeVal tv; #endif multi_debug("wait for manual event locks"); #if GLIB_CHECK_VERSION (2,32,0) g_mutex_lock(&condMutex); end_time = g_get_monotonic_time() + 10 * G_TIME_SPAN_SECOND; #else g_mutex_lock(condMutex); #endif while (!ME->signalled) { multi_debug("waiting for manual event"); #if GLIB_CHECK_VERSION (2,32,0) if (!g_cond_wait_until(&ME->cond, &condMutex, end_time)) #else g_get_current_time(&tv); g_time_val_add(&tv, 10 * 1000 * 1000); if (g_cond_timed_wait(ME->cond, condMutex, &tv)) #endif break; else { multi_debug("still waiting for manual event"); } } #if GLIB_CHECK_VERSION (2,32,0) g_mutex_unlock(&condMutex); #else g_mutex_unlock(condMutex); #endif multi_debug("wait for manual event unlocks"); }
void mode_displaysleep_tick_tock() { multi_debug("mode_displaysleep_tick_tock\n"); pulse_cancel_timer(&modeDisplaysleepingTimerID); assert(modeDisplaysleepingTimerID == -1); modeDisplaysleepingTimerID = pulse_register_timer(10000, // slow &mode_displaysleep_tick_tock, 0); // pulse assert(modeDisplaysleepingTimerID != -1); mode_displaysleep_draw_digit(0, multiTimeNow.tm_hour / 10); // Digit *?:?? mode_displaysleep_draw_digit(1, multiTimeNow.tm_hour % 10); // Digit ?*:?? // position 2 has the colon! mode_displaysleep_draw_digit(3, multiTimeNow.tm_min / 10); // Digit ??:*? mode_displaysleep_draw_digit(4, multiTimeNow.tm_min % 10); // Digit ??:?* }
void MT_AddTask(Task * pt, gboolean lock) { if (lock) { Mutex_Lock(td.queueLock, "add task"); } if (td.addedTasks == 0) td.result = 0; /* Reset result for new tasks */ td.addedTasks++; td.tasks = g_list_append(td.tasks, pt); if (g_list_length(td.tasks) == 1) { /* New tasks */ SetManualEvent(td.activity); } if (lock) { multi_debug("add task: release"); Mutex_Release(td.queueLock); } }
static Task * MT_GetTask(void) { Task *task = NULL; Mutex_Lock(td.queueLock, "get task"); if (g_list_length(td.tasks) > 0) { task = (Task *) g_list_first(td.tasks)->data; td.tasks = g_list_delete_link(td.tasks, g_list_first(td.tasks)); if (g_list_length(td.tasks) == 0) { ResetManualEvent(td.activity); } } multi_debug("get task: release"); Mutex_Release(td.queueLock); return task; }
void mode_btlostphone_watch_functions(const enum multi_function_table iFunc) { //multi_debug("enum %i\n", iFunc); switch (iFunc) { case COLDBOOT: mode_btlostphone_alarm_ignore = false; break; // No MODEINIT since all vars are globally used when the face is not visible case BUTTONWAKE: mode_btlostphone_update_screen = true; break; case MAINLOOP: if (mode_btlostphone_update_screen) { mode_btlostphone_draw_watch_face(); mode_btlostphone_update_screen = false; } break; case BUTTONUP: mode_btlostphone_alarm_ignore = !mode_btlostphone_alarm_ignore; //break; // fall through to hardware change to reset timer etc case HARDWARECHANGE: multi_debug("HARDWARECHANGE\n"); // BUTTONUP falls through here... // IMPORTANT: may not be active watch face so no screen output mode_btlostphone_update_screen = true; // if active it will update // Reset our "timer" mode_btlostphone_min = -1; //break; // Falls through to APPLOOP to buzz immediately case APPLOOP: // HARDWARECHANGE falls through here // Hence no screen output allowed if (!multiBluetoothIsConnected && !mode_btlostphone_alarm_ignore) { mode_btlostphone_apploop(); } break; default: // ignore features we do not use break; } }
void mt_add_tasks(unsigned int num_tasks, AsyncFun pFun, void *taskData, gpointer linked) { unsigned int i; { #ifdef DEBUG_MULTITHREADED char buf[20]; sprintf(buf, "add %u tasks", num_tasks); Mutex_Lock(td.queueLock, buf); #else Mutex_Lock(td.queueLock, NULL); #endif } for (i = 0; i < num_tasks; i++) { Task *pt = (Task *) malloc(sizeof(Task)); pt->fun = pFun; pt->data = taskData; pt->pLinkedTask = linked; MT_AddTask(pt, FALSE); } multi_debug("add many release: lock"); Mutex_Release(td.queueLock); }
// It's time to sleep! void mode_displaysleep_power_down() { multi_debug("mode_displaysleep_power_down - time to sleep\n"); // Immediately stop the watch doing anything else multi_external_sleep_init(); pulse_cancel_timer(&modeDisplaysleepPowerDownTimerID); // pulse // Clear the display pulse_blank_canvas(); pulse_oled_set_brightness(0); // dark // Clear our positions for (int i=0; i<MODE_DISPLAYSLEEP_DIGIT_POS_SIZE; i++) { modeDisplaysleepCurrentlyDisplayed[i] = MODE_DISPLAYSLEEP_NO_DIGIT; } // Display the colon mode_displaysleep_draw_digit(2, 10); // Digit ??*?? <-- colon // Now start the proper loop mode_displaysleep_tick_tock(); }
int MT_WaitForTasks(gboolean(*pCallback) (gpointer), int callbackTime, int autosave) { GList *member; guint cb_source = 0; guint as_source = 0; td.doneTasks = 0; #if USE_GTK GTKSuspendInput(); #endif multi_debug("Waiting for all tasks"); pCallback(NULL); cb_source = g_timeout_add(1000, pCallback, NULL); if (autosave) as_source = g_timeout_add(nAutoSaveTime * 60000, save_autosave, NULL); for (member = g_list_first(td.tasks); member; member = member->next, td.doneTasks++) { Task *task = member->data; task->fun(task->data); free(task->pLinkedTask); free(task); ProcessEvents(); } g_list_free(td.tasks); if (autosave) { g_source_remove(as_source); save_autosave(NULL); } td.tasks = NULL; #if USE_GTK GTKResumeInput(); #endif return td.result; }
void mode_demo_main_loop() { multi_debug("main loop\n"); printf("MAINLOOP\n"); }
void mode_demo_bluetooth_received() { multi_debug("mode_demo_bluetooth_received\n"); printf("BLUETOOTHREC\nFirst byte was %i\n", multiBluetoothRecBuffer[0]); }
void mode_demo_button_up() { multi_debug("mode_demo_button_up\n"); printf("BUTTONUP\n"); }
void mode_demo_button_down_long_press() { multi_debug("mode_demo_button_down_long_press\n"); printf("BUTTONDOWNLONGPRESS\n"); }
static gboolean WaitingForThreads(gpointer UNUSED(unused)) { /* Unlikely to be called */ multi_debug("Waiting for threads to be created!"); return FALSE; }
void mode_demo_button_down() { multi_debug("mode_demo_button_down\n"); printf("BUTTONDOWN\n"); }
void mode_demo_woken_by_button() { multi_debug("mode_demo_woken_by_button\n"); printf("BUTTONWAKE\n"); printf("My face name %s\n", multiMyWatchFaceName); }
void Mutex_Release(Mutex mutex) { multi_debug("Releasing lock"); ReleaseMutex(mutex); }
void mode_demo_cold_boot() { multi_debug("cold boot\n"); printf("COLDBOOT\nThe display is not really available...\n"); pulse_mdelay(1000); }