int pthread_tryjoin_np ( pthread_t threadid, void **thread_return) { struct pthread *self; struct pthread *pd = (struct pthread *) threadid; /* Make sure the descriptor is valid. */ if (DEBUGGING_P && __find_in_stack_list (pd) == NULL) /* Not a valid thread handle. */ return ESRCH; /* Is the thread joinable?. */ if (IS_DETACHED (pd)) /* We cannot wait for the thread. */ return EINVAL; self = THREAD_SELF; if (pd == self || self->joinid == pd) /* This is a deadlock situation. The threads are waiting for each other to finish. Note that this is a "may" error. To be 100% sure we catch this error we would have to lock the data structures but it is not necessary. In the unlikely case that two threads are really caught in this situation they will deadlock. It is the programmer's problem to figure this out. */ return EDEADLK; /* Return right away if the thread hasn't terminated yet. */ if (pd->tid != 0) return EBUSY; /* Wait for the thread to finish. If it is already locked something is wrong. There can only be one waiter. */ if (atomic_compare_and_exchange_bool_acq (&pd->joinid, self, NULL)) /* There is already somebody waiting for the thread. */ return EINVAL; /* Store the return value if the caller is interested. */ if (thread_return != NULL) *thread_return = pd->result; /* Free the TCB. */ __free_tcb (pd); return 0; }
void WorkspacePane::DoShowTab(bool show, const wxString& title) { if(!show) { for(size_t i = 0; i < m_book->GetPageCount(); i++) { if(m_book->GetPageText(i) == title) { // we've got a match m_book->RemovePage(i); wxWindow* win = DoGetControlByName(title); if(win) { win->Show(false); } break; } } } else { for(size_t i = 0; i < m_book->GetPageCount(); i++) { if(m_book->GetPageText(i) == title) { // requested to add a page which already exists return; } } // Fetch the list of detached panes // If the mainframe is NULL, read the // list from the disk, otherwise use the // dockable pane menu // Read it from the disk DetachedPanesInfo dpi; EditorConfigST::Get()->ReadObject(wxT("DetachedPanesList"), &dpi); wxArrayString detachedPanes; detachedPanes = dpi.GetPanes(); if(IS_DETACHED(title)) return; wxWindow* win = DoGetControlByName(title); if(win) { win->Show(true); m_book->InsertPage(0, win, title, true); } } }
int pthread_getattr_np ( pthread_t thread_id, pthread_attr_t *attr) { struct pthread *thread = (struct pthread *) thread_id; struct pthread_attr *iattr = (struct pthread_attr *) attr; int ret = 0; lll_lock (thread->lock, LLL_PRIVATE); /* The thread library is responsible for keeping the values in the thread desriptor up-to-date in case the user changes them. */ memcpy (&iattr->schedparam, &thread->schedparam, sizeof (struct sched_param)); iattr->schedpolicy = thread->schedpolicy; /* Clear the flags work. */ iattr->flags = thread->flags; /* The thread might be detached by now. */ if (IS_DETACHED (thread)) iattr->flags |= ATTR_FLAG_DETACHSTATE; /* This is the guardsize after adjusting it. */ iattr->guardsize = thread->reported_guardsize; /* The sizes are subject to alignment. */ if (__builtin_expect (thread->stackblock != NULL, 1)) { iattr->stacksize = thread->stackblock_size; iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize; } else { /* No stack information available. This must be for the initial thread. Get the info in some magical way. */ assert (abs (thread->pid) == thread->tid); /* Stack size limit. */ struct rlimit rl; /* The safest way to get the top of the stack is to read /proc/self/maps and locate the line into which __libc_stack_end falls. */ FILE *fp = fopen ("/proc/self/maps", "rc"); if (fp == NULL) ret = errno; /* We need the limit of the stack in any case. */ else { if (getrlimit (RLIMIT_STACK, &rl) != 0) ret = errno; else { /* We need no locking. */ __fsetlocking (fp, FSETLOCKING_BYCALLER); /* Until we found an entry (which should always be the case) mark the result as a failure. */ ret = ENOENT; char *line = NULL; size_t linelen = 0; uintptr_t last_to = 0; while (! feof_unlocked (fp)) { if (getdelim (&line, &linelen, '\n', fp) <= 0) break; uintptr_t from; uintptr_t to; if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2) continue; if (from <= (uintptr_t) __libc_stack_end && (uintptr_t) __libc_stack_end < to) { /* Found the entry. Now we have the info we need. */ iattr->stacksize = rl.rlim_cur; iattr->stackaddr = (void *) to; /* The limit might be too high. */ if ((size_t) iattr->stacksize > (size_t) iattr->stackaddr - last_to) iattr->stacksize = (size_t) iattr->stackaddr - last_to; /* We succeed and no need to look further. */ ret = 0; break; } last_to = to; } free (line); } fclose (fp); } } iattr->flags |= ATTR_FLAG_STACKADDR; if (ret == 0) { size_t size = 16; cpu_set_t *cpuset = NULL; do { size <<= 1; void *newp = realloc (cpuset, size); if (newp == NULL) { ret = ENOMEM; break; } cpuset = (cpu_set_t *) newp; ret = __pthread_getaffinity_np (thread_id, size, cpuset); } /* Pick some ridiculous upper limit. Is 8 million CPUs enough? */ while (ret == EINVAL && size < 1024 * 1024); if (ret == 0) { iattr->cpuset = cpuset; iattr->cpusetsize = size; } else { free (cpuset); if (ret == ENOSYS) { /* There is no such functionality. */ ret = 0; iattr->cpuset = NULL; iattr->cpusetsize = 0; } } } lll_unlock (thread->lock, LLL_PRIVATE); return ret; }
static int do_clone (struct pthread *pd, const struct pthread_attr *attr, int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS, int stopped) { #ifdef PREPARE_CREATE PREPARE_CREATE; #endif if (stopped) /* We Make sure the thread does not run far by forcing it to get a lock. We lock it here too so that the new thread cannot continue until we tell it to. */ lll_lock (pd->lock); /* One more thread. We cannot have the thread do this itself, since it might exist but not have been scheduled yet by the time we've returned and need to check the value to behave correctly. We must do it before creating the thread, in case it does get scheduled first and then might mistakenly think it was the only thread. In the failure case, we momentarily store a false value; this doesn't matter because there is no kosher thing a signal handler interrupting us right here can do that cares whether the thread count is correct. */ atomic_increment (&__nptl_nthreads); if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1) { atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */ /* Failed. If the thread is detached, remove the TCB here since the caller cannot do this. The caller remembered the thread as detached and cannot reverify that it is not since it must not access the thread descriptor again. */ if (IS_DETACHED (pd)) __deallocate_stack (pd); return errno; } /* Now we have the possibility to set scheduling parameters etc. */ if (__builtin_expect (stopped != 0, 0)) { INTERNAL_SYSCALL_DECL (err); int res = 0; /* Set the affinity mask if necessary. */ if (attr->cpuset != NULL) { res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, sizeof (cpu_set_t), attr->cpuset); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) { /* The operation failed. We have to kill the thread. First send it the cancellation signal. */ INTERNAL_SYSCALL_DECL (err2); err_out: #if __ASSUME_TGKILL (void) INTERNAL_SYSCALL (tgkill, err2, 3, THREAD_GETMEM (THREAD_SELF, pid), pd->tid, SIGCANCEL); #else (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL); #endif return (INTERNAL_SYSCALL_ERROR_P (res, err) ? INTERNAL_SYSCALL_ERRNO (res, err) : 0); } } /* Set the scheduling parameters. */ if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0) { res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid, pd->schedpolicy, &pd->schedparam); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) goto err_out; } } /* We now have for sure more than one thread. The main thread might not yet have the flag set. No need to set the global variable again if this is what we use. */ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); return 0; }
void DebuggerPane::CreateGUIControls() { wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL); SetSizer(mainSizer); long style = (kNotebook_Default | kNotebook_AllowDnD); if(!EditorConfigST::Get()->GetOptions()->GetWorkspaceTabsDirection()) { style |= kNotebook_BottomTabs; } if(EditorConfigST::Get()->GetOptions()->IsTabColourDark()) { style &= ~kNotebook_LightTabs; style |= kNotebook_DarkTabs; } if(EditorConfigST::Get()->GetOptions()->IsMouseScrollSwitchTabs()) { style |= kNotebook_MouseScrollSwitchTabs; } style |= kNotebook_UnderlineActiveTab; GeneralImages img; m_book = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style); mainSizer->Add(m_book, 1, wxEXPAND | wxALL, 0); // Calculate the widthest tab (the one with the 'Call Stack' label) int xx, yy; wxFont fnt = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); wxWindow::GetTextExtent(_("Breakpoints"), &xx, &yy, NULL, NULL, &fnt); // load list of detached panes wxArrayString detachedPanes; DetachedPanesInfo dpi; EditorConfigST::Get()->ReadObject(wxT("DetachedPanesList"), &dpi); detachedPanes = dpi.GetPanes(); wxString name; wxBitmap bmp; name = wxGetTranslation(LOCALS); bmp = wxXmlResource::Get()->LoadBitmap(wxT("locals_view")); // Add the 'Locals View' if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_localsTable = new LocalsTable(cp); cp->SetChildNoReparent(m_localsTable); } else { m_localsTable = new LocalsTable(m_book); m_book->AddPage(m_localsTable, name, false, bmp); } // Add the 'watches View' name = wxGetTranslation(WATCHES); bmp = wxXmlResource::Get()->LoadBitmap(wxT("watches")); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_watchesTable = new WatchesTable(cp); cp->SetChildNoReparent(m_watchesTable); } else { m_watchesTable = new WatchesTable(m_book); m_book->AddPage(m_watchesTable, name, false, bmp); } // Add the 'ASCII Viewer' name = wxGetTranslation(ASCII_VIEWER); bmp = wxXmlResource::Get()->LoadBitmap(wxT("text_view")); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_asciiViewer = new DebuggerAsciiViewer(cp); cp->SetChildNoReparent(m_asciiViewer); } else { m_asciiViewer = new DebuggerAsciiViewer(m_book); m_book->AddPage(m_asciiViewer, name, false, bmp); } // Add the 'Call Stack' name = wxGetTranslation(FRAMES); bmp = wxXmlResource::Get()->LoadBitmap(wxT("frames")); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_frameList = new DebuggerCallstackView(cp); cp->SetChildNoReparent(m_frameList); } else { m_frameList = new DebuggerCallstackView(m_book); m_book->AddPage(m_frameList, name, false, bmp); } // Add the 'Breakpoints' name = wxGetTranslation(BREAKPOINTS); bmp = wxXmlResource::Get()->LoadBitmap(wxT("breakpoint")); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_breakpoints = new BreakpointDlg(cp); cp->SetChildNoReparent(m_breakpoints); } else { m_breakpoints = new BreakpointDlg(m_book); m_book->AddPage(m_breakpoints, name, false, bmp); } // Add the 'Threads' name = wxGetTranslation(THREADS); bmp = wxXmlResource::Get()->LoadBitmap(wxT("threads")); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_threads = new ThreadListPanel(cp); cp->SetChildNoReparent(m_threads); } else { m_threads = new ThreadListPanel(m_book); m_book->AddPage(m_threads, name, false, bmp); } // Add the 'Memory View' name = wxGetTranslation(MEMORY); bmp = wxXmlResource::Get()->LoadBitmap(wxT("memory_view")); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_memory = new MemoryView(cp); cp->SetChildNoReparent(m_memory); } else { m_memory = new MemoryView(m_book); m_book->AddPage(m_memory, name, false, bmp); } // Add the "Output" tab name = wxGetTranslation(DEBUGGER_OUTPUT); bmp = wxXmlResource::Get()->LoadBitmap(wxT("debugger_tab")); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_outputDebug = new DebugTab(cp, wxID_ANY, wxGetTranslation(DEBUGGER_OUTPUT)); cp->SetChildNoReparent(m_outputDebug); } else { m_outputDebug = new DebugTab(m_book, wxID_ANY, wxGetTranslation(DEBUGGER_OUTPUT)); m_book->AddPage(m_outputDebug, name, false, bmp); } // Add the "Output" tab name = wxGetTranslation(DISASSEMBLY); bmp = img.Bitmap("dbgAsm"); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, bmp, wxSize(200, 200)); m_disassemble = new DebuggerDisassemblyTab(cp, wxGetTranslation(DISASSEMBLY)); cp->SetChildNoReparent(m_disassemble); } else { m_disassemble = new DebuggerDisassemblyTab(m_book, wxGetTranslation(DISASSEMBLY)); m_book->AddPage(m_disassemble, name, false, bmp); } m_book->Bind(wxEVT_BOOK_PAGE_CHANGED, &DebuggerPane::OnPageChanged, this); m_initDone = true; }
void WorkspacePane::CreateGUIControls() { wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL); SetSizer(mainSizer); // add notebook for tabs #ifdef __WXOSX__ long style = (kNotebook_Default | kNotebook_AllowDnD | kNotebook_LeftTabs); #else long style = (kNotebook_Default | kNotebook_AllowDnD); #endif if(EditorConfigST::Get()->GetOptions()->IsTabColourDark()) { style &= ~kNotebook_LightTabs; style |= kNotebook_DarkTabs; } style |= kNotebook_UnderlineActiveTab; if(EditorConfigST::Get()->GetOptions()->IsMouseScrollSwitchTabs()) { style |= kNotebook_MouseScrollSwitchTabs; } m_book = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style); m_book->SetTabDirection(EditorConfigST::Get()->GetOptions()->GetWorkspaceTabsDirection()); m_book->SetArt(GetNotebookRenderer()); // Calculate the widest tab (the one with the 'Workspace' label) int xx, yy; wxFont fnt = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); wxWindow::GetTextExtent(_("Workspace"), &xx, &yy, NULL, NULL, &fnt); mainSizer->Add(m_book, 1, wxEXPAND | wxALL, 0); // Add the parsing progress controls m_staticText = new wxStaticText(this, wxID_ANY, _("Parsing workspace...")); mainSizer->Add(m_staticText, 0, wxEXPAND | wxALL, 2); m_parsingProgress = new wxGauge(this, wxID_ANY, 100, wxDefaultPosition, wxSize(-1, 15), wxGA_HORIZONTAL | wxGA_SMOOTH); mainSizer->Add(m_parsingProgress, 0, wxEXPAND | wxALL, 1); m_parsingProgress->Hide(); m_staticText->Hide(); // create tabs (possibly detached) DetachedPanesInfo dpi; EditorConfigST::Get()->ReadObject(wxT("DetachedPanesList"), &dpi); wxArrayString detachedPanes; detachedPanes = dpi.GetPanes(); // Add the workspace tab wxString name; // the IManager instance IManager* mgr = PluginManager::Get(); name = _("Workspace"); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, wxNullBitmap, wxSize(200, 200)); m_workspaceTab = new WorkspaceTab(cp, name); cp->SetChildNoReparent(m_workspaceTab); } else { m_workspaceTab = new WorkspaceTab(m_book, name); m_book->AddPage(m_workspaceTab, name, true, wxNullBitmap); } m_tabs.insert(std::make_pair(name, Tab(name, m_workspaceTab))); mgr->AddWorkspaceTab(name); // Add the explorer tab name = _("Explorer"); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, wxNullBitmap, wxSize(200, 200)); m_explorer = new FileExplorer(cp, name); cp->SetChildNoReparent(m_explorer); } else { m_explorer = new FileExplorer(m_book, name); m_book->AddPage(m_explorer, name, false); } m_tabs.insert(std::make_pair(name, Tab(name, m_explorer))); mgr->AddWorkspaceTab(name); // Add the "File Explorer" view to the list of files managed by the workspace-view m_workspaceTab->GetView()->AddPage(m_explorer, _("File Explorer"), false); // Add the Open Windows Panel (Tabs) #ifndef __WXOSX__ name = _("Tabs"); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, wxNullBitmap, wxSize(200, 200)); m_openWindowsPane = new OpenWindowsPanel(cp, name); cp->SetChildNoReparent(m_openWindowsPane); } else { m_openWindowsPane = new OpenWindowsPanel(m_book, name); m_book->AddPage(m_openWindowsPane, name, false); } m_tabs.insert(std::make_pair(name, Tab(name, m_openWindowsPane))); mgr->AddWorkspaceTab(name); #endif // Add the Tabgroups tab name = _("Tabgroups"); if(IS_DETACHED(name)) { DockablePane* cp = new DockablePane(GetParent(), m_book, name, false, wxNullBitmap, wxSize(200, 200)); m_TabgroupsPane = new TabgroupsPane(cp, name); cp->SetChildNoReparent(m_TabgroupsPane); } else { m_TabgroupsPane = new TabgroupsPane(m_book, name); m_book->AddPage(m_TabgroupsPane, name, false); } m_tabs.insert(std::make_pair(name, Tab(name, m_TabgroupsPane))); mgr->AddWorkspaceTab(name); if(m_book->GetPageCount() > 0) { m_book->SetSelection((size_t)0); } m_mgr->Update(); }
int pthread_timedjoin_np ( pthread_t threadid, void **thread_return, const struct timespec *abstime) { struct pthread *self; struct pthread *pd = (struct pthread *) threadid; int result; /* Make sure the descriptor is valid. */ if (INVALID_NOT_TERMINATED_TD_P (pd)) /* Not a valid thread handle. */ return ESRCH; /* Is the thread joinable?. */ if (IS_DETACHED (pd)) /* We cannot wait for the thread. */ return EINVAL; self = THREAD_SELF; if (pd == self || self->joinid == pd) /* This is a deadlock situation. The threads are waiting for each other to finish. Note that this is a "may" error. To be 100% sure we catch this error we would have to lock the data structures but it is not necessary. In the unlikely case that two threads are really caught in this situation they will deadlock. It is the programmer's problem to figure this out. */ return EDEADLK; /* Wait for the thread to finish. If it is already locked something is wrong. There can only be one waiter. */ if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid, self, NULL), 0)) /* There is already somebody waiting for the thread. */ return EINVAL; /* During the wait we change to asynchronous cancellation. If we are cancelled the thread we are waiting for must be marked as un-wait-ed for again. */ pthread_cleanup_push (cleanup, &pd->joinid); /* Switch to asynchronous cancellation. */ int oldtype = CANCEL_ASYNC (); /* Wait for the child. */ result = lll_timedwait_tid (pd->tid, abstime); /* Restore cancellation mode. */ CANCEL_RESET (oldtype); /* Remove the handler. */ pthread_cleanup_pop (0); /* We might have timed out. */ if (result == 0) { /* Store the return value if the caller is interested. */ if (thread_return != NULL) *thread_return = pd->result; /* Free the TCB. */ __free_tcb (pd); } else pd->joinid = NULL; return result; }
void WorkspacePane::CreateGUIControls() { wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL); SetSizer(mainSizer); // add notebook for tabs long bookStyle = wxVB_LEFT | wxAUI_NB_WINDOWLIST_BUTTON; m_book = new Notebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, bookStyle); // Calculate the widest tab (the one with the 'Workspace' label) int xx, yy; wxFont fnt = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); wxWindow::GetTextExtent(_("Workspace"), &xx, &yy, NULL, NULL, &fnt); mainSizer->Add(m_book, 1, wxEXPAND | wxALL, 0); // Add the parsing progress controls m_staticText = new wxStaticText(this, wxID_ANY, _("Parsing workspace...")); mainSizer->Add(m_staticText, 0, wxEXPAND|wxALL, 2); m_parsingProgress = new wxGauge(this, wxID_ANY, 100, wxDefaultPosition, wxSize(-1, 15), wxGA_HORIZONTAL|wxGA_SMOOTH); mainSizer->Add(m_parsingProgress, 0, wxEXPAND|wxALL, 1); m_parsingProgress->Hide(); m_staticText->Hide(); // create tabs (possibly detached) DetachedPanesInfo dpi; EditorConfigST::Get()->ReadObject(wxT("DetachedPanesList"), &dpi); wxArrayString detachedPanes; detachedPanes = dpi.GetPanes(); // Add the workspace tab wxString name; name = _("Workspace"); if(IS_DETACHED(name)) { DockablePane *cp = new DockablePane(GetParent(), m_book, name, wxNullBitmap, wxSize(200, 200)); m_workspaceTab = new WorkspaceTab(cp, name); cp->SetChildNoReparent(m_workspaceTab); } else { m_workspaceTab = new WorkspaceTab(m_book, name); m_book->AddPage(m_workspaceTab, name, true, wxNullBitmap); } // Add the explorer tab name = _("Explorer"); if(IS_DETACHED(name)) { DockablePane *cp = new DockablePane(GetParent(), m_book, name, wxNullBitmap, wxSize(200, 200)); m_explorer = new FileExplorer(cp, name); cp->SetChildNoReparent(m_explorer); } else { m_explorer = new FileExplorer(m_book, name); m_book->AddPage(m_explorer, name, false); } // Add the Open Windows Panel (Tabs) name = _("Tabs"); if(IS_DETACHED(name)) { DockablePane *cp = new DockablePane(GetParent(), m_book, name, wxNullBitmap, wxSize(200, 200)); m_openWindowsPane = new OpenWindowsPanel(cp, name); cp->SetChildNoReparent(m_openWindowsPane); } else { m_openWindowsPane = new OpenWindowsPanel(m_book, name); m_book->AddPage(m_openWindowsPane, name, false); } // Add the Tabgroups tab name = _("Tabgroups"); if(IS_DETACHED(name)) { DockablePane *cp = new DockablePane(GetParent(), m_book, name, wxNullBitmap, wxSize(200, 200)); m_TabgroupsPane = new TabgroupsPane(cp, name); cp->SetChildNoReparent(m_TabgroupsPane); } else { m_TabgroupsPane = new TabgroupsPane(m_book, name); m_book->AddPage(m_TabgroupsPane, name, false); } if (m_book->GetPageCount() > 0) { m_book->SetSelection((size_t)0); } UpdateTabs(); m_mgr->Update(); }
static int do_clone (struct pthread *pd, const struct pthread_attr *attr, int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS, int stopped) { #if 0 PREPARE_CREATE; #endif if (__builtin_expect (stopped != 0, 0)) /* We make sure the thread does not run far by forcing it to get a lock. We lock it here too so that the new thread cannot continue until we tell it to. */ lll_lock (pd->lock, LLL_PRIVATE); /* One more thread. We cannot have the thread do this itself, since it might exist but not have been scheduled yet by the time we've returned and need to check the value to behave correctly. We must do it before creating the thread, in case it does get scheduled first and then might mistakenly think it was the only thread. In the failure case, we momentarily store a false value; this doesn't matter because there is no kosher thing a signal handler interrupting us right here can do that cares whether the thread count is correct. */ atomic_increment (&__nptl_nthreads); #if !defined(__native_client__) && !defined(__ZRT_HOST) #error "This code was changed to work only in Native Client" #endif /* Native Client does not have a notion of a thread ID, so we make one up. This must be small enough to leave space for number identifying the clock. Use CLOCK_IDFIELD_SIZE to guarantee that. */ pd->tid = ((unsigned int) pd) >> CLOCK_IDFIELD_SIZE; /* Native Client syscall thread_create does not push return address onto stack as opposed to the kernel. We emulate this behavior on x86-64 to meet the ABI requirement ((%rsp + 8) mod 16 == 0). On x86-32 the attribute 'force_align_arg_pointer' does the same for start_thread (). */ #ifdef __x86_64__ STACK_VARIABLES_ARGS -= 8; #endif if (__nacl_irt_thread_create (fct, STACK_VARIABLES_ARGS, pd) != 0) { pd->tid = 0; atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */ /* Failed. If the thread is detached, remove the TCB here since the caller cannot do this. The caller remembered the thread as detached and cannot reverify that it is not since it must not access the thread descriptor again. */ if (IS_DETACHED (pd)) __deallocate_stack (pd); /* We have to translate error codes. */ return errno == ENOMEM ? EAGAIN : errno; } /* Now we have the possibility to set scheduling parameters etc. */ if (__builtin_expect (stopped != 0, 0)) { INTERNAL_SYSCALL_DECL (err); int res = 0; /* Set the affinity mask if necessary. */ if (attr->cpuset != NULL) { res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, attr->cpusetsize, attr->cpuset); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) { /* The operation failed. We have to kill the thread. First send it the cancellation signal. */ INTERNAL_SYSCALL_DECL (err2); err_out: #if __ASSUME_TGKILL (void) INTERNAL_SYSCALL (tgkill, err2, 3, THREAD_GETMEM (THREAD_SELF, pid), pd->tid, SIGCANCEL); #else (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL); #endif return (INTERNAL_SYSCALL_ERROR_P (res, err) ? INTERNAL_SYSCALL_ERRNO (res, err) : 0); } } /* Set the scheduling parameters. */ if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0) { res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid, pd->schedpolicy, &pd->schedparam); if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) goto err_out; } } /* We now have for sure more than one thread. The main thread might not yet have the flag set. No need to set the global variable again if this is what we use. */ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); return 0; }