/* * wait for a lock to be granted */ static inline struct rw_semaphore *rwsem_down_failed_common(struct rw_semaphore *sem, struct rwsem_waiter *waiter, signed long adjustment) { struct task_struct *tsk = current; signed long count; set_task_state(tsk,TASK_UNINTERRUPTIBLE); /* set up my own style of waitqueue */ spin_lock(&sem->wait_lock); waiter->task = tsk; list_add_tail(&waiter->list,&sem->wait_list); /* note that we're now waiting on the lock, but no longer actively read-locking */ count = rwsem_atomic_update(adjustment,sem); /* if there are no longer active locks, wake the front queued process(es) up * - it might even be this process, since the waker takes a more active part */ if (!(count & RWSEM_ACTIVE_MASK)) sem = __rwsem_do_wake(sem,1); spin_unlock(&sem->wait_lock); /* wait to be given the lock */ for (;;) { if (!waiter->flags) break; schedule(); set_task_state(tsk, TASK_UNINTERRUPTIBLE); } tsk->state = TASK_RUNNING; return sem; }
void wq_wait(struct waitqueue_head *q) { unsigned irqflag; DEFINE_WAIT(wait); spin_lock_irqsave(q->lock, irqflag); if (list_empty(&wait.link)) list_add(&wait.link, q->list.prev); set_task_state(current, TASK_WAITING); spin_unlock_irqrestore(q->lock, irqflag); schedule(); }
void my_timer(unsigned long data) { struct task_struct * task = (struct task_struct *)data; printk("Kernel Timer Time-Out Function Doing...\n"); printk(KERN_WARNING "[SK_DD]my_timer=>proc_state_%d:%lx!!\n", task->pid, task->state); set_task_state(task, EXIT_DEAD); //include/linux/sched.h //set_task_state(task, EXIT_ZOMBIE); //include/linux/sched.h //set_task_state(task, TASK_RUNNING); //include/linux/sched.h //__activate_task(task, rq); printk(KERN_WARNING "[SK_DD]my_timer=>proc_state_%d:%lx!!\n", task->pid, task->state); printk("Kernel Timer Time-Out Function Done!!!\n"); }
int ACTIVE_TASK::resume_or_start(bool first_time) { if (log_flags.task) { msg_printf(result->project, MSG_INFO, "[task] %s task %s: FLOPS left %.2fG", first_time?"Starting":"Resuming", result->name, result->sim_flops_left/1e9 ); } set_task_state(PROCESS_EXECUTING, "start"); char buf[256]; sprintf(buf, "Starting %s<br> %s<br> deadline %s<br>", result->name, result->project->get_project_name(), sim_time_string(result->report_deadline) ); html_msg += buf; return 0; }
int task_kill_self(struct task_struct *task) { struct task_struct *system_killer = pid_get_task(0); if (!system_killer) return -EINVAL; /* * when a task try to kill himself, need to * wake up system_killer process to help doing * this */ kernel_debug("Kill self\n"); set_task_state(task, PROCESS_STATE_IDLE); wakeup_task(system_killer); sched(); return 0; }
void wq_wake(struct waitqueue_head *q, int nr_task) { struct list *p = q->list.next; struct task *task; unsigned irqflag; spin_lock_irqsave(q->lock, irqflag); while (p != &q->list && nr_task) { task = get_container_of(p, struct waitqueue, link)->task; set_task_state(task, TASK_RUNNING); runqueue_add(task); list_del(p); p = q->list.next; nr_task--; } spin_unlock_irqrestore(q->lock, irqflag); }
void down_read_failed_biased(struct rw_semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */ for (;;) { if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0)) break; set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!sem->read_bias_granted) schedule(); } remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; }
static void psnedf_task_wake_up(struct task_struct *task) { unsigned long flags; psnedf_domain_t* pedf = task_pedf(task); rt_domain_t* edf = task_edf(task); lt_t now; TRACE_TASK(task, "wake_up at %llu\n", litmus_clock()); raw_readyq_lock_irqsave(&pedf->slock, flags); set_task_state(task, TASK_RUNNING); BUG_ON(is_queued(task)); now = litmus_clock(); if (is_sporadic(task) && is_tardy(task, now) #ifdef CONFIG_LITMUS_LOCKING /* We need to take suspensions because of semaphores into * account! If a job resumes after being suspended due to acquiring * a semaphore, it should never be treated as a new job release. */ && !is_priority_boosted(task) #endif ) { /* new sporadic release */ release_at(task, now); sched_trace_task_release(task); } budget_state_machine(task,on_wakeup); /* Only add to ready queue if it is not the currently-scheduled * task. This could be the case if a task was woken up concurrently * on a remote CPU before the executing CPU got around to actually * de-scheduling the task, i.e., wake_up() raced with schedule() * and won. */ if (pedf->scheduled != task) { requeue(task, edf); psnedf_preempt_check(pedf); } raw_readyq_unlock_irqrestore(&pedf->slock, flags); TRACE_TASK(task, "wake up done\n"); }
/* coverity[+kill] */ void __noreturn lbug_with_loc(struct libcfs_debug_msg_data *msgdata) { libcfs_catastrophe = 1; libcfs_debug_msg(msgdata, "LBUG\n"); if (in_interrupt()) { panic("LBUG in interrupt.\n"); /* not reached */ } dump_stack(); if (!libcfs_panic_on_lbug) libcfs_debug_dumplog(); if (libcfs_panic_on_lbug) panic("LBUG"); set_task_state(current, TASK_UNINTERRUPTIBLE); while (1) schedule(); }
/* Wait for the lock to become unbiased. Since we're * a writer, we'll make ourselves exclusive. */ void down_write_failed(struct rw_semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); up_write(sem); /* this takes care of granting the lock */ add_wait_queue_exclusive(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); } remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; }
int __sched __down_failed_interruptible(struct semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); long ret = 0; #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down failed(%p)\n", tsk->comm, tsk->pid, sem); #endif tsk->state = TASK_INTERRUPTIBLE; wmb(); add_wait_queue_exclusive(&sem->wait, &wait); while (__sem_update_count(sem, -1) <= 0) { if (signal_pending(current)) { /* * A signal is pending - give up trying. * Set sem->count to 0 if it is negative, * since we are no longer sleeping. */ __sem_update_count(sem, 0); ret = -EINTR; break; } schedule(); set_task_state(tsk, TASK_INTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down %s(%p)\n", current->comm, current->pid, (ret < 0 ? "interrupted" : "acquired"), sem); #endif return ret; }
int wake_up_process(struct task_struct *tsk) { int need_resched = 0; if (tsk->state == TASK_UNINTERRUPTIBLE) return -1; if (!pri_bitmap) need_resched = 1; struct task_struct *next = pick_next_task(); if (next->prio >= tsk->prio) need_resched = 1; set_task_state(tsk, TASK_RUNNING); if (need_resched) set_tsk_need_resched(current); return 0; }
void __sched __down_failed(struct semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down failed(%p)\n", tsk->comm, tsk->pid, sem); #endif tsk->state = TASK_UNINTERRUPTIBLE; wmb(); add_wait_queue_exclusive(&sem->wait, &wait); /* * Try to get the semaphore. If the count is > 0, then we've * got the semaphore; we decrement count and exit the loop. * If the count is 0 or negative, we set it to -1, indicating * that we are asleep, and then sleep. */ while (__sem_update_count(sem, -1) <= 0) { schedule(); set_task_state(tsk, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; /* * If there are any more sleepers, wake one of them up so * that it can either get the semaphore, or set count to -1 * indicating that there are still processes sleeping. */ wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down acquired(%p)\n", tsk->comm, tsk->pid, sem); #endif }
/* Wait for the lock to become unbiased. Readers * are non-exclusive. =) */ struct rw_semaphore *down_read_failed(struct rw_semaphore *sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); /* this takes care of granting the lock */ __up_op_read(sem, __rwsem_wake); add_wait_queue(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= 0) break; schedule(); } remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; return sem; }
static int __init make_init_task() { extern void idle(); /* becomes init task */ /* stack must be allocated first. and to build root relationship * properly `current` must be set to `init`. */ current = &init; if (alloc_mm(&init, NULL, 0)) return -ERR_ALLOC; set_task_dressed(&init, TASK_STATIC | TASK_KERNEL, idle); set_task_context_hard(&init, wrapper); set_task_pri(&init, LOW_PRIORITY); set_task_state(&init, TASK_RUNNING); /* make it the sole */ list_link_init(&init.children); list_link_init(&init.sibling); return 0; }
/* * get a write lock on the semaphore */ void __sched __down_write_nested(struct rw_semaphore *sem, int subclass) { struct rwsem_waiter waiter; struct task_struct *tsk; unsigned long flags; raw_spin_lock_irqsave(&sem->wait_lock, flags); #ifdef CONFIG_BRCM_DEBUG_RWSEM sem->wr_owner = current; #endif /* set up my own style of waitqueue */ tsk = current; waiter.task = tsk; waiter.type = RWSEM_WAITING_FOR_WRITE; list_add_tail(&waiter.list, &sem->wait_list); /* wait for someone to release the lock */ for (;;) { /* * That is the key to support write lock stealing: allows the * task already on CPU to get the lock soon rather than put * itself into sleep and waiting for system woke it or someone * else in the head of the wait list up. */ if (sem->activity == 0) break; set_task_state(tsk, TASK_UNINTERRUPTIBLE); raw_spin_unlock_irqrestore(&sem->wait_lock, flags); schedule(); raw_spin_lock_irqsave(&sem->wait_lock, flags); } /* got the lock */ sem->activity = -1; list_del(&waiter.list); raw_spin_unlock_irqrestore(&sem->wait_lock, flags); }
void event_configure_notify(Window win) { // change in root window (xrandr) if (win == server.root_win) { signal_pending = SIGUSR1; return; } // 'win' is a trayer icon TrayWindow* traywin; GSList* l; for (l = systray.list_icons; l; l = l->next) { traywin = (TrayWindow*)l->data; if (traywin->tray_id == win) { XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, traywin->width, traywin->height); XResizeWindow(server.dsp, traywin->tray_id, traywin->width, traywin->height); panel_refresh = 1; return; } } // 'win' move in another monitor if (nb_panel == 1) return; Task* tsk = task_get_task(win); if (!tsk) return; Panel* p = tsk->area.panel; if (p->monitor != window_get_monitor(win)) { remove_task(tsk); tsk = add_task(win); if (win == window_get_active()) { set_task_state(tsk, TASK_ACTIVE); task_active = tsk; } panel_refresh = 1; } }
static int dispose_iface(struct device *dev) { struct keywest_iface *iface = dev_get_drvdata(dev); int i, rc; /* Make sure we stop all activity */ down(&iface->sem); spin_lock_irq(&iface->lock); while (iface->state != state_idle) { spin_unlock_irq(&iface->lock); set_task_state(current,TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); spin_lock_irq(&iface->lock); } iface->state = state_dead; spin_unlock_irq(&iface->lock); free_irq(iface->irq, iface); up(&iface->sem); /* Release all channels */ for (i=0; i<iface->chan_count; i++) { struct keywest_chan* chan = &iface->channels[i]; if (i2c_get_adapdata(&chan->adapter) == NULL) continue; rc = i2c_del_adapter(&chan->adapter); i2c_set_adapdata(&chan->adapter, NULL); /* We aren't that prepared to deal with this... */ if (rc) printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n"); } iounmap((void *)iface->base); dev_set_drvdata(dev, NULL); kfree(iface); return 0; }
static ssize_t wup_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { int want_to_sleep = 0; spin_lock(&lock); if (!p) { p = current; want_to_sleep = 1; } spin_unlock(&lock); if (want_to_sleep) { set_task_state(current, TASK_UNINTERRUPTIBLE); schedule(); /* wake_up_process が呼ばれるまで眠る */ spin_lock(&lock); p = NULL; spin_unlock(&lock); } return 0; }
static void __init load_user_task() { extern char _user_task_list; struct task *p; unsigned int pri; for (p = (struct task *)&_user_task_list; *(unsigned int *)p; p++) { if (p->addr == NULL) continue; /* share the init kernel stack to save memory */ if (alloc_mm(p, &init, STACK_SHARED)) continue; pri = get_task_pri(p); set_task_dressed(p, p->flags | STACK_SHARED, p->addr); set_task_pri(p, pri); set_task_context(p, wrapper); /* make it runnable, and add into runqueue */ set_task_state(p, TASK_RUNNING); runqueue_add(p); } }
Task *add_task (Window win) { if (!win) return 0; if (window_is_hidden(win)) return 0; int monitor; if (nb_panel > 1) { monitor = window_get_monitor (win); if (monitor >= nb_panel) monitor = 0; } else monitor = 0; Task new_tsk; new_tsk.win = win; new_tsk.desktop = window_get_desktop (win); new_tsk.area.panel = &panel1[monitor]; new_tsk.current_state = window_is_iconified(win) ? TASK_ICONIFIED : TASK_NORMAL; window_get_coordinates (win, &new_tsk.geometry); // allocate only one title and one icon // even with task_on_all_desktop and with task_on_all_panel new_tsk.title = 0; int k; for (k=0; k<TASK_STATE_COUNT; ++k) { new_tsk.icon[k] = 0; new_tsk.state_pix[k] = 0; } get_title(&new_tsk); get_icon(&new_tsk); //printf("task %s : desktop %d, monitor %d\n", new_tsk->title, desktop, monitor); XSelectInput (server.dsp, new_tsk.win, PropertyChangeMask|StructureNotifyMask); GPtrArray* task_group = g_ptr_array_new(); Taskbar *tskbar; Task *new_tsk2=0; for (uint32_t j=0, desktop_count = panel1[monitor].nb_desktop; j < desktop_count ; j++) { if (new_tsk.desktop != ALLDESKTOP && new_tsk.desktop != j) continue; tskbar = &panel1[monitor].taskbar[j]; new_tsk2 = calloc(1, sizeof(Task)); memcpy(&new_tsk2->area, &panel1[monitor].g_task.area, sizeof(Area)); new_tsk2->area.parent = tskbar; new_tsk2->win = new_tsk.win; new_tsk2->desktop = new_tsk.desktop; /* new_tsk2->win_x = new_tsk.win_x; */ /* new_tsk2->win_y = new_tsk.win_y; */ /* new_tsk2->win_w = new_tsk.win_w; */ /* new_tsk2->win_h = new_tsk.win_h; */ new_tsk2->geometry = new_tsk.geometry; new_tsk2->current_state = -1; // to update the current state later in set_task_state... if (new_tsk2->desktop == ALLDESKTOP && server.desktop != (int)j) { // hide ALLDESKTOP task on non-current desktop new_tsk2->area.visible = 0; } new_tsk2->title = new_tsk.title; if (panel1[monitor].g_task.tooltip_enabled) new_tsk2->area._get_tooltip_text = task_get_tooltip; for (k=0; k<TASK_STATE_COUNT; ++k) { new_tsk2->icon[k] = new_tsk.icon[k]; new_tsk2->state_pix[k] = 0; } new_tsk2->icon_width = new_tsk.icon_width; new_tsk2->icon_height = new_tsk.icon_height; tskbar->area.children = g_slist_append(tskbar->area.children, new_tsk2); tskbar->area.resize = 1; g_ptr_array_add(task_group, new_tsk2); //printf("add_task panel %d, desktop %d, task %s\n", i, j, new_tsk2->title); } Window* key = calloc(1, sizeof(Window)); *key = new_tsk.win; g_hash_table_insert(win_to_task_table, key, task_group); set_task_state(new_tsk2, new_tsk.current_state); sort_taskbar_for_win(win); if (panel_mode == MULTI_DESKTOP) { Panel *panel = new_tsk2->area.panel; panel->area.resize = 1; } if (window_is_urgent(win)) { add_urgent(new_tsk2); } return new_tsk2; }
void event_property_notify(XEvent* e) { int i; Task* tsk; Window win = e->xproperty.window; Atom at = e->xproperty.atom; if (xsettings_client) xsettings_client_process_event(xsettings_client, e); if (win == server.root_win) { if (!server.got_root_win) { XSelectInput(server.dsp, server.root_win, PropertyChangeMask | StructureNotifyMask); server.got_root_win = 1; } // Change name of desktops else if (at == server.atom._NET_DESKTOP_NAMES) { if (!taskbarname_enabled) return; GSList* l, *list = server_get_name_of_desktop(); gchar* name; Taskbar* tskbar; for (i = 0; i < nb_panel; i++) { l = list; for (uint8_t j = 0; j < panel1[i].desktop_count; j++) { if (l) { name = g_strdup(l->data); l = l->next; } else name = g_strdup_printf("%d", j + 1); tskbar = &panel1[i].taskbar[j]; if (strcmp(name, tskbar->bar_name.name) != 0) { g_free(tskbar->bar_name.name); tskbar->bar_name.name = name; tskbar->bar_name.area.resize = 1; } else g_free(name); } } for (l = list; l; l = l->next) g_free(l->data); g_slist_free(list); panel_refresh = 1; } // Change number of desktops else if (at == server.atom._NET_NUMBER_OF_DESKTOPS) { if (!taskbar_enabled) return; server.nb_desktop = server_get_number_of_desktop(); if (server.nb_desktop <= server.desktop) { server.desktop = server.nb_desktop - 1; } cleanup_taskbar(); init_taskbar(); for (i = 0; i < nb_panel; i++) { init_taskbar_panel(&panel1[i]); set_panel_items_order(&panel1[i]); visible_taskbar(&panel1[i]); panel1[i].area.resize = 1; } task_refresh_tasklist(); active_task(); panel_refresh = 1; } // Change desktop else if (at == server.atom._NET_CURRENT_DESKTOP) { if (!taskbar_enabled) return; int old_desktop = server.desktop; server.desktop = server_get_current_desktop(); for (i = 0; i < nb_panel; i++) { Panel* panel = &panel1[i]; set_taskbar_state(&panel->taskbar[old_desktop], TASKBAR_NORMAL); set_taskbar_state(&panel->taskbar[server.desktop], TASKBAR_ACTIVE); // check ALLDESKTOP task => resize taskbar Taskbar* tskbar; Task* tsk; GSList* l; if (server.nb_desktop > old_desktop) { tskbar = &panel->taskbar[old_desktop]; l = tskbar->area.list; if (taskbarname_enabled) l = l->next; for (; l; l = l->next) { tsk = l->data; if (tsk->desktop == ALLDESKTOP) { tsk->area.on_screen = 0; tskbar->area.resize = 1; panel_refresh = 1; } } } tskbar = &panel->taskbar[server.desktop]; l = tskbar->area.list; if (taskbarname_enabled) l = l->next; for (; l; l = l->next) { tsk = l->data; if (tsk->desktop == ALLDESKTOP) { tsk->area.on_screen = 1; tskbar->area.resize = 1; } } } } // Window list else if (at == server.atom._NET_CLIENT_LIST) { task_refresh_tasklist(); panel_refresh = 1; } // Change active else if (at == server.atom._NET_ACTIVE_WINDOW) { active_task(); panel_refresh = 1; } else if (at == server.atom._XROOTPMAP_ID || at == server.atom._XROOTMAP_ID) { // change Wallpaper for (i = 0; i < nb_panel; i++) { set_panel_background(&panel1[i]); } panel_refresh = 1; } } else { tsk = task_get_task(win); if (!tsk) { if (at != server.atom._NET_WM_STATE) return; else { // xfce4 sends _NET_WM_STATE after minimized to tray, so we need to // check if window is mapped // if it is mapped and not set as skip_taskbar, we must add it to our // task list XWindowAttributes wa; XGetWindowAttributes(server.dsp, win, &wa); if (wa.map_state == IsViewable && !window_is_skip_taskbar(win)) { if ((tsk = add_task(win))) panel_refresh = 1; else return; } else return; } } // Window title changed if (at == server.atom._NET_WM_VISIBLE_NAME || at == server.atom._NET_WM_NAME || at == server.atom.WM_NAME) { if (get_title(tsk)) { if (g_tooltip.mapped && (g_tooltip.area == (Area*)tsk)) { tooltip_copy_text((Area*)tsk); tooltip_update(); } panel_refresh = 1; } } // Demand attention else if (at == server.atom._NET_WM_STATE) { if (window_is_urgent(win)) { add_urgent(tsk); } if (window_is_skip_taskbar(win)) { remove_task(tsk); panel_refresh = 1; } } else if (at == server.atom.WM_STATE) { // Iconic state int state = (task_active && tsk->win == task_active->win ? TASK_ACTIVE : TASK_NORMAL); if (window_is_iconified(win)) state = TASK_ICONIFIED; set_task_state(tsk, state); panel_refresh = 1; } // Window icon changed else if (at == server.atom._NET_WM_ICON) { get_icon(tsk); panel_refresh = 1; } // Window desktop changed else if (at == server.atom._NET_WM_DESKTOP) { uint32_t desktop = window_get_desktop(win); // bug in windowmaker : send unecessary 'desktop changed' when focus // changed if (desktop != tsk->desktop) { remove_task(tsk); tsk = add_task(win); active_task(); panel_refresh = 1; } } else if (at == server.atom.WM_HINTS) { XWMHints* wmhints = XGetWMHints(server.dsp, win); if (wmhints && wmhints->flags & XUrgencyHint) { add_urgent(tsk); } XFree(wmhints); } if (!server.got_root_win) server.root_win = RootWindow(server.dsp, server.screen); } }
/// Start a task in a slot directory. /// This includes setting up soft links, /// passing preferences, and starting the process. /// /// Current dir is top-level Synecdoche dir. /// /// \post /// - If any error occurs /// - #task_state is #PROCESS_COULDNT_START /// - CLIENT_STATE::report_result_error() is called /// - else /// - #task_state is #PROCESS_EXECUTING /// /// \return 0 on success, nonzero otherwise. int ACTIVE_TASK::start() { char exec_name[256], exec_path[256]; unsigned int i; FILE_REF fref; int retval; // F*** goto, need to define some variables here instead of where they are used! std::ostringstream err_stream; #ifdef _WIN32 std::string cmd_line; std::string slotdirpath; #else // Needs to be defined here because those gotos would skip the // initialization of 'cmdline' and 'argv' if it would be defined later. std::ostringstream cmdline; std::list<std::string> argv; #endif if ((!full_init_done) && (log_flags.task)) { msg_printf(wup->project, MSG_INFO, "Starting %s", result->name ); } if (log_flags.cpu_sched) { msg_printf(wup->project, MSG_INFO, "[cpu_sched] Starting %s%s", result->name, (full_init_done) ? " (resume)" : " (initial)" ); } // Always check if all required files are present. If not, trigger // re-downloads and don't start the science application. FILE_INFO_PSET missing_file_infos; retval = gstate.input_files_available(result, true, &missing_file_infos); if (retval) { for (FILE_INFO_PSET::iterator it = missing_file_infos.begin(); it != missing_file_infos.end(); ++it) { FILE_INFO* fip = *it; if (fip) { err_stream << "Input file " << fip->name << " missing or invalid: " << retval; } else { err_stream << "Input file missing or invalid"; // We can't trigger a new download if we don't have // any file information. Just fail here as before. goto error; } fip->status = FILE_NOT_PRESENT; } } if (!missing_file_infos.empty()) { // Some files are missing and are set for re-transfer. // Update status and return without error. result->set_state(RESULT_FILES_DOWNLOADING, "start"); set_task_state(PROCESS_UNINITIALIZED, "start"); next_scheduler_state = PROCESS_UNINITIALIZED; return 0; } if (!full_init_done) { checkpoint_cpu_time = 0; checkpoint_wall_time = gstate.now; } current_cpu_time = checkpoint_cpu_time; episode_start_cpu_time = checkpoint_cpu_time; debt_interval_start_cpu_time = checkpoint_cpu_time; graphics_request_queue.init(result->name); // reset message queues process_control_queue.init(result->name); if (!app_client_shm.shm) { retval = get_shmem_seg_name(); if (retval) { err_stream << "Can't get shared memory segment name: " << boincerror(retval); goto error; } } // this must go AFTER creating shmem name, // since the shmem name is part of the file // retval = write_app_init_file(); if (retval) { err_stream << "Can't write init file: " << retval; goto error; } // set up applications files // strcpy(exec_name, ""); for (i=0; i<app_version->app_files.size(); i++) { fref = app_version->app_files[i]; FILE_INFO* fip = fref.file_info; std::string file_path = get_pathname(fip); if (fref.main_program) { if (is_image_file(fip->name)) { err_stream << "Main program " << fip->name << " is an image file"; retval = ERR_NO_SIGNATURE; goto error; } if (!fip->executable && !wup->project->anonymous_platform) { err_stream << "Main program " << fip->name << " is not executable"; retval = ERR_NO_SIGNATURE; goto error; } safe_strcpy(exec_name, fip->name.c_str()); safe_strcpy(exec_path, file_path.c_str()); } // anonymous platform may use different files than // when the result was started, so link files even if not first time if ((!full_init_done) || (wup->project->anonymous_platform)) { retval = setup_file(result->project, fip, fref, file_path, slot_dir, true); if (retval) { err_stream << "Can't link input file"; goto error; } } } if (!strlen(exec_name)) { err_stream << "No main program specified"; retval = ERR_NOT_FOUND; goto error; } // set up input, output files if (!full_init_done) { for (i=0; i<wup->input_files.size(); i++) { fref = wup->input_files[i]; const FILE_INFO* fip = fref.file_info; std::string file_path = get_pathname(fref.file_info); retval = setup_file(result->project, fip, fref, file_path, slot_dir, true); if (retval) { err_stream << "Can't link input file"; goto error; } } for (i=0; i<result->output_files.size(); i++) { fref = result->output_files[i]; if (fref.copy_file) continue; const FILE_INFO* fip = fref.file_info; std::string file_path = get_pathname(fref.file_info); retval = setup_file(result->project, fip, fref, file_path, slot_dir, false); if (retval) { err_stream << "Can't link output file"; goto error; } } full_init_done = true; } link_user_files(); if (gstate.exit_before_start) { exit(0); } #ifdef _WIN32 PROCESS_INFORMATION process_info; STARTUPINFO startup_info; LPVOID environment_block = NULL; char error_msg[1024]; char error_msg2[1024]; memset(&process_info, 0, sizeof(process_info)); memset(&startup_info, 0, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); // suppress 2-sec rotating hourglass cursor on startup // startup_info.dwFlags = STARTF_FORCEOFFFEEDBACK; app_client_shm.reset_msgs(); if (config.run_apps_manually) { // fill in core client's PID so we won't think app has exited pid = GetCurrentProcessId(); pid_handle = GetCurrentProcess(); set_task_state(PROCESS_EXECUTING, "start"); return 0; } // NOTE: in Windows, stderr is redirected in boinc_init_diagnostics(); cmd_line = exec_path + std::string(" ") + wup->command_line; if (strlen(app_version->cmdline)) { cmd_line += std::string(" ") + app_version->cmdline; } slotdirpath = relative_to_absolute(slot_dir); bool success = false; for (i=0; i<5; i++) { if (sandbox_account_service_token != NULL) { // Find CreateEnvironmentBlock/DestroyEnvironmentBlock pointers tCEB pCEB = NULL; tDEB pDEB = NULL; HMODULE hUserEnvLib = NULL; hUserEnvLib = LoadLibrary("userenv.dll"); if (hUserEnvLib) { pCEB = (tCEB) GetProcAddress(hUserEnvLib, "CreateEnvironmentBlock"); pDEB = (tDEB) GetProcAddress(hUserEnvLib, "DestroyEnvironmentBlock"); } if (!pCEB(&environment_block, sandbox_account_service_token, FALSE)) { if (log_flags.task) { windows_error_string(error_msg, sizeof(error_msg)); msg_printf(wup->project, MSG_INFO, "Process environment block creation failed: %s", error_msg ); } } if (CreateProcessAsUser( sandbox_account_service_token, exec_path, (LPSTR)cmd_line.c_str(), NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW|IDLE_PRIORITY_CLASS|CREATE_UNICODE_ENVIRONMENT, environment_block, slotdirpath.c_str(), &startup_info, &process_info )) { success = true; break; } else { windows_error_string(error_msg, sizeof(error_msg)); msg_printf(wup->project, MSG_INTERNAL_ERROR, "Process creation failed: %s", error_msg ); } if (!pDEB(environment_block)) { if (log_flags.task) { windows_error_string(error_msg, sizeof(error_msg2)); msg_printf(wup->project, MSG_INFO, "Process environment block cleanup failed: %s", error_msg2 ); } } if (hUserEnvLib) { pCEB = NULL; pDEB = NULL; FreeLibrary(hUserEnvLib); } } else { if (CreateProcess( exec_path, (LPSTR)cmd_line.c_str(), NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW|IDLE_PRIORITY_CLASS, NULL, slotdirpath.c_str(), &startup_info, &process_info )) { success = true; break; } else { windows_error_string(error_msg, sizeof(error_msg)); msg_printf(wup->project, MSG_INTERNAL_ERROR, "Process creation failed: %s", error_msg ); } } boinc_sleep(drand()); } if (!success) { err_stream << "CreateProcess() failed - " << error_msg; retval = ERR_EXEC; goto error; } pid = process_info.dwProcessId; pid_handle = process_info.hProcess; CloseHandle(process_info.hThread); // thread handle is not used #else // Unix/Linux/Mac case // Set up core/app shared memory seg if needed // if (!app_client_shm.shm) { if (app_version->api_major_version() >= 6) { // Use mmap() shared memory std::string buf = slot_dir + std::string("/") + std::string(MMAPPED_FILE_NAME); if (g_use_sandbox) { if (!boinc_file_exists(buf.c_str())) { int fd = open(buf.c_str(), O_RDWR | O_CREAT, 0660); if (fd >= 0) { close (fd); #ifdef SANDBOX set_to_project_group(buf.c_str()); #endif } } } retval = create_shmem_mmap( buf.c_str(), sizeof(SHARED_MEM), (void**)&app_client_shm.shm ); } else { // Use shmget() shared memory retval = create_shmem( shmem_seg_name, sizeof(SHARED_MEM), gstate.boinc_project_gid, (void**)&app_client_shm.shm ); if (retval) { needs_shmem = true; destroy_shmem(shmem_seg_name); return retval; } } needs_shmem = false; } app_client_shm.reset_msgs(); #if (defined (__APPLE__) && (defined(__i386__) || defined(__x86_64__))) // PowerPC apps emulated on i386 Macs crash if running graphics powerpc_emulated_on_i386 = ! is_native_i386_app(exec_path); #endif if (config.run_apps_manually) { pid = getpid(); // use the client's PID set_task_state(PROCESS_EXECUTING, "start"); return 0; } // Prepare command line for the science app: cmdline << wup->command_line; if (strlen(app_version->cmdline)) { cmdline << ' ' << app_version->cmdline; } argv = parse_command_line(cmdline.str().c_str()); if (log_flags.task_debug) { debug_print_argv(argv); } pid = fork(); if (pid == -1) { err_stream << "fork() failed: " << strerror(errno); retval = ERR_FORK; goto error; } if (pid == 0) { // from here on we're running in a new process. // If an error happens, // exit nonzero so that the core client knows there was a problem. // don't pass stdout to the app // int fd = open("/dev/null", O_RDWR); dup2(fd, STDOUT_FILENO); close(fd); // add to library path: // - the project dir (../../projects/X) // - the slot dir (.) // - the Synecdoche dir (../..) // We use relative paths in case higher-level dirs // are not readable to the account under which app runs // std::string pdir = get_project_dir(wup->project); std::ostringstream libpath; const char* env_lib_path = getenv("LD_LIBRARY_PATH"); if (env_lib_path) { libpath << env_lib_path << ':'; } libpath << "../../" << pdir << ":.:../.."; setenv("LD_LIBRARY_PATH", libpath.str().c_str(), 1); retval = chdir(slot_dir.c_str()); if (retval) { perror("chdir"); fflush(NULL); _exit(errno); } #if 0 // set stack size limit to the max. // Some BOINC apps have reported problems with exceeding // small stack limits (e.g. 8 MB) // and it seems like the best thing to raise it as high as possible // struct rlimit rlim; #define MIN_STACK_LIMIT 64000000 getrlimit(RLIMIT_STACK, &rlim); if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur <= MIN_STACK_LIMIT) { if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max > MIN_STACK_LIMIT) { rlim.rlim_cur = MIN_STACK_LIMIT; } else { rlim.rlim_cur = rlim.rlim_max; } setrlimit(RLIMIT_STACK, &rlim); } #endif // hook up stderr to a specially-named file // freopen(STDERR_FILE, "a", stderr); // set idle process priority #ifdef HAVE_SETPRIORITY if (setpriority(PRIO_PROCESS, 0, PROCESS_IDLE_PRIORITY)) { perror("setpriority"); } #endif std::string path = std::string("../../") + std::string(exec_path); if (g_use_sandbox) { std::ostringstream switcher_path; switcher_path << "../../" << SWITCHER_DIR << '/' << SWITCHER_FILE_NAME; argv.push_front(exec_name); argv.push_front(path); argv.push_front(SWITCHER_FILE_NAME); // Files written by projects have user boinc_project and group boinc_project, // so they must be world-readable so Synecdoche can read them. umask(2); retval = do_execv(switcher_path.str(), argv); } else { argv.push_front(exec_name); retval = do_execv(path, argv); } msg_printf(wup->project, MSG_INTERNAL_ERROR, "Process creation (%s) failed: %s, errno=%d\n", path.c_str(), boincerror(retval), errno ); perror("execv"); fflush(NULL); _exit(errno); } if (log_flags.task_debug) { msg_printf(wup->project, MSG_INFO, "[task_debug] ACTIVE_TASK::start(): forked process: pid %d\n", pid ); } #endif set_task_state(PROCESS_EXECUTING, "start"); return 0; // go here on error; "error_msg" contains error message, "retval" is nonzero // error: // if something failed, it's possible that the executable was munged. // Verify it to trigger another download. // gstate.input_files_available(result, true); gstate.report_result_error(*result, "%s", err_stream.str().c_str()); set_task_state(PROCESS_COULDNT_START, "start"); return retval; }
/* * Lock a mutex (possibly interruptible), slowpath: */ static inline int __mutex_lock_common(struct mutex *lock, long state) { struct task_struct *task = current; struct mutex_waiter waiter; unsigned int old_val; unsigned long flags; spin_lock_mutex(&lock->wait_lock, flags); /* add waiting tasks to the end of the waitqueue (FIFO): */ list_add_tail(&waiter.list, &lock->wait_list); waiter.task = task; old_val = atomic_xchg(&lock->count, -1); if (old_val == 1) goto done; for (;;) { /* * Lets try to take the lock again - this is needed even if * we get here for the first time (shortly after failing to * acquire the lock), to make sure that we get a wakeup once * it's unlocked. Later on, if we sleep, this is the * operation that gives us the lock. We xchg it to -1, so * that when we release the lock, we properly wake up the * other waiters: */ old_val = atomic_xchg(&lock->count, -1); if (old_val == 1) break; /* * got a signal? (This code gets eliminated in the * TASK_UNINTERRUPTIBLE case.) */ #if 0 if (unlikely((state == TASK_INTERRUPTIBLE && signal_pending(task)) || (state == TASK_KILLABLE && fatal_signal_pending(task)))) { mutex_remove_waiter(lock, &waiter, task_thread_info(task)); spin_unlock_mutex(&lock->wait_lock, flags); return -EINTR; } #endif set_task_state(task, state); /* didnt get the lock, go to sleep: */ spin_unlock_mutex(&lock->wait_lock, flags); schedule(); spin_lock_mutex(&lock->wait_lock, flags); } done: /* got the lock - rejoice! */ mutex_remove_waiter(lock, &waiter, task_thread_info(task)); /* set it to 0 if there are no waiters left: */ if (likely(list_empty(&lock->wait_list))) atomic_set(&lock->count, 0); spin_unlock_mutex(&lock->wait_lock, flags); return 0; }
int remove_from_rq(pcontext *pcb) { set_task_state(pcb, SLEEPING); return remove_task(pcb, 0); }
int wake_up_task(void *pcb) { pcb = (pcontext *)pcb; set_task_state(pcb, READY); return insert_task(pcb); }
/* * Setup MobiCore kernel log. It assumes it's running on CORE 0! * The fastcall will complain is that is not the case! */ long mobicore_log_setup(void) { unsigned long phys_log_buf; union fc_generic fc_log; struct sched_param param = { .sched_priority = 1 }; long ret; log_pos = 0; log_buf = NULL; log_thread = NULL; log_line = NULL; log_line_len = 0; prev_eol = false; prev_source = 0; thread_err = 0; /* Sanity check for the log size */ if (log_size < PAGE_SIZE) return -EFAULT; else log_size = PAGE_ALIGN(log_size); log_line = kzalloc(LOG_LINE_SIZE, GFP_KERNEL); if (IS_ERR(log_line)) { MCDRV_DBG_ERROR(mcd, "failed to allocate log line!"); return -ENOMEM; } log_thread = kthread_create(log_worker, NULL, "mc_log"); if (IS_ERR(log_thread)) { MCDRV_DBG_ERROR(mcd, "MobiCore log thread creation failed!"); ret = -EFAULT; goto err_free_line; } sched_setscheduler(log_thread, SCHED_IDLE, ¶m); /* * We are going to map this buffer into virtual address space in SWd. * To reduce complexity there, we use a contiguous buffer. */ log_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(log_size)); if (!log_buf) { MCDRV_DBG_ERROR(mcd, "Failed to get page for logger!"); ret = -ENOMEM; goto err_stop_kthread; } phys_log_buf = virt_to_phys(log_buf); memset(&fc_log, 0, sizeof(fc_log)); fc_log.as_in.cmd = MC_FC_NWD_TRACE; fc_log.as_in.param[0] = phys_log_buf; fc_log.as_in.param[1] = log_size; MCDRV_DBG(mcd, "fc_log virt=%p phys=%p ", log_buf, (void *)phys_log_buf); mc_fastcall(&fc_log); MCDRV_DBG(mcd, "fc_log out ret=0x%08x", fc_log.as_out.ret); /* If the setup failed we must free the memory allocated */ if (fc_log.as_out.ret) { MCDRV_DBG_ERROR(mcd, "MobiCore shared traces setup failed!"); free_pages((unsigned long)log_buf, get_order(log_size)); log_buf = NULL; ret = -EIO; goto err_stop_kthread; } set_task_state(log_thread, TASK_INTERRUPTIBLE); MCDRV_DBG(mcd, "fc_log Logger version %u\n", log_buf->version); return 0; err_stop_kthread: kthread_stop(log_thread); log_thread = NULL; err_free_line: kfree(log_line); log_line = NULL; return ret; } /* * Free kernel log components. * ATTN: We can't free the log buffer because it's also in use by MobiCore and * even if the module is unloaded MobiCore is still running. */ void mobicore_log_free(void) { if (log_thread && !IS_ERR(log_thread)) { /* We don't really care what the thread returns for exit */ kthread_stop(log_thread); } kfree(log_line); }
void serialchar_callback(struct serial_info *serial) { set_task_state(serial->owner, TASK_RUNNING); schedule(); }
int ACTIVE_TASK::request_exit() { set_task_state(PROCESS_UNINITIALIZED, "request_exit"); return 0; }