int treat_action(t_socket *sock, struct sockaddr_in addr) { int i; int addrl; char buff[21]; addrl = sizeof(addr); if ((sock->tmp_sock = accept(sock->main_sock, (struct sockaddr *)&addr, (socklen_t *)&addrl)) < 0) write(2, "Accept new connection failed\n", 29); i = read(sock->tmp_sock, buff, 20); buff[i] = '\0'; if ((i = -1) && check_pseudo(sock, buff) == -1) return (-1); if (write(1, buff, my_strlen(buff)) < 0 || write(1, " is now connected\n", 18) < 0) return (-1); while (++i < MAX_CLIENTS) if (sock->cli_sock[i] == 0 && !(sock->status[i] = 0)) { sock->cli_sock[i] = sock->tmp_sock; send_list_cli(sock, sock->cli_sock[i], sock->pseudo[i]); notify_all(sock, sock->pseudo[i], 1); break; } return (0); }
void Text::cut() { // ---- check for reasonable selection ---- unsigned line1 = selection_.line1(); unsigned line2 = selection_.line2(); unsigned column1 = selection_.column1(); unsigned column2 = selection_.column2(); if ((line1 > line2) || ((line1 == line2) && (column1 >= column2))) { return; } // ---- copy to cut/copy/paste buffer ---- copy(); // ---- remove from text buffer --- int index0 = text_->LineIndex(line1) + column1; int index1 = text_->LineIndex(line2) + column2; int len = index1 - index0 + 1; text_->Delete(index0, len); // ---- update view ---- insertion_.line_ = selection_.line1(); insertion_.column_ = selection_.column1(); selection_.line2(selection_.line1()); selection_.column2(selection_.column1()); needWidth_ = true; dirty(true); notify_all(); damage(); }
s32 sys_rwlock_runlock(u32 rw_lock_id) { sys_rwlock.Log("sys_rwlock_runlock(rw_lock_id=0x%x)", rw_lock_id); LV2_LOCK; const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); if (!rwlock) { return CELL_ESRCH; } if (!rwlock->readers) { return CELL_EPERM; } if (!--rwlock->readers) { rwlock->notify_all(lv2_lock); } return CELL_OK; }
/** * Add a host to the list and notify clients about this event * * @param identity the identity of the host * @return the HostEntry */ static struct HostEntry * add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity) { struct HostEntry *entry; struct ReadHostFileContext r; char *fn; entry = GNUNET_CONTAINER_multipeermap_get (hostmap, identity); if (NULL == entry) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding new peer `%s'\n", GNUNET_i2s (identity)); GNUNET_STATISTICS_update (stats, gettext_noop ("# peers known"), 1, GNUNET_NO); entry = GNUNET_new (struct HostEntry); entry->identity = *identity; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (hostmap, &entry->identity, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); notify_all (entry); fn = get_host_filename (identity); if (NULL != fn) { read_host_file (fn, GNUNET_YES, &r); if (NULL != r.hello) update_hello (identity, r.hello); if (NULL != r.friend_only_hello) update_hello (identity, r.friend_only_hello); GNUNET_free_non_null (r.hello); GNUNET_free_non_null (r.friend_only_hello); GNUNET_free (fn); } }
~distributor() { lock(); done = true; notify_all(); unlock(); threads.join(); }
void ept_invalidate_addr(paddr_t gpaddr) { /* See Vol3B 24.3.3 */ if (TRUNC_PAGE(gpaddr) == kvtophys(dma_test_page)) { kprintf("ept_invalidate_addr>gpaddr = "PFMT"\n", gpaddr); } #ifdef HYP_PAE notify_all((nb_func_t)__ept_invalidate_addr, (nb_arg_t)bits(gpaddr, 31, 0), (nb_arg_t)bits(gpaddr, 63, 32)); #else notify_all((nb_func_t)__ept_invalidate_addr, (nb_arg_t)gpaddr, (nb_arg_t)0); #endif }
void Text::backspace() { if ((insertion_.column_ <= 0) && (insertion_.line_ > 0)) { --insertion_.line_; if (insertion_.line_ >= text_->Height()) { insertion_.column_ = 0; } else { // --- update insertion point --- int index = text_->LineIndex(insertion_.line_); //insertion_.column_ = text_->LineOffset(index); // ---- delete the character ---- int delIndex = text_->EndOfLine(index); insertion_.column_ = delIndex - index; text_->Delete(delIndex, 1); } needWidth_ = true; notify_all(); damage(); // !!! could only damage from insertion to end of window } else if (insertion_.column_ > 0) { int oldWidth = text_->Width(); int index = text_->LineIndex(insertion_.line_); // ---- delete the text --- text_->Delete(index + insertion_.column_ - 1, 1); --insertion_.column_; if (text_->Width() != oldWidth) { needWidth_ = true; notify_all(); } repair(); damage(insertion_); repair(); } }
void Text::font(const Font* f) { Resource::ref(f); Resource::unref(font_); font_ = f; needWidth_ = true; notify_all(); damage(); }
void erts_ddll_lock_driver(DE_Handle *dh, char *name) { DE_ProcEntry *p,*q; assert_drv_list_rwlocked(); notify_all(dh, name, ERL_DE_PROC_AWAIT_LOAD, am_UP, am_permanent); notify_all(dh, name, ERL_DE_PROC_AWAIT_UNLOAD, am_UP, am_permanent); notify_all(dh, name, ERL_DE_PROC_AWAIT_UNLOAD_ONLY, am_UP, am_permanent); p = dh->procs; while(p != NULL) { q = p; p = p->next; erts_free(ERTS_ALC_T_DDLL_PROCESS, (void *) q); } dh->procs = NULL; erts_ddll_reference_driver(dh); dh->status = ERL_DE_PERMANENT; }
/** * Function that is called on each HELLO file in a particular directory. * Try to parse the file and add the HELLO to our list. * * @param cls pointer to 'unsigned int' to increment for each file, or NULL * if the file is from a read-only, read-once resource directory * @param fullname name of the file to parse * @return GNUNET_OK (continue iteration) */ static int hosts_directory_scan_callback (void *cls, const char *fullname) { unsigned int *matched = cls; struct GNUNET_PeerIdentity identity; const char *filename; struct HostEntry *entry; struct GNUNET_HELLO_Message *hello; if (GNUNET_DISK_file_test (fullname) != GNUNET_YES) return GNUNET_OK; /* ignore non-files */ if (strlen (fullname) < sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) { if (NULL != matched) remove_garbage (fullname); return GNUNET_OK; } filename = &fullname[strlen (fullname) - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1]; if (filename[-1] != DIR_SEPARATOR) { if (NULL != matched) remove_garbage (fullname); return GNUNET_OK; } if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (filename, &identity.hashPubKey)) { if (NULL != (hello = read_host_file (filename))) { entry = GNUNET_malloc (sizeof (struct HostEntry)); if (GNUNET_OK == GNUNET_HELLO_get_id (hello, &entry->identity)) { GNUNET_CONTAINER_multihashmap_put (hostmap, &entry->identity.hashPubKey, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); entry->hello = hello; notify_all (entry); return GNUNET_OK; } GNUNET_free (entry); } if (NULL != matched) remove_garbage (fullname); return GNUNET_OK; } if (NULL != matched) (*matched)++; add_host_to_known_hosts (&identity); return GNUNET_OK; }
void Text::insertChars(const char* txt, unsigned count) { TextBuffer text(txt, count, count); // ---- insert the text info the buffer ---- text_->Insert(text_->LineIndex(insertion_.line_) + insertion_.column_, txt, count); dirty(true); if (text.Height() > 1) { TextRegion area; area.line1(insertion_.line_); area.column1(0); area.line2(insertion_.line_ + text.Height() - 1); area.column2(0); insertion_.line_ += text.Height() - 1; insertion_.column_ = 0; damage(); // !!! could only damage from insertion to end of window for (unsigned i = 0; i < text.Height(); ++i) { width_ = Math::max(width_, width(text.getNth(i))); } notify_all(); } else { TextLocation old = insertion_; insertion_.column_ += count; Coord newWidth = width(text_->getNth(insertion_.line_)); if (newWidth >= width_) { width_ = Math::max(width_, newWidth); notify_all(); } repair(); damage(old); repair(); } }
base_artificial_table_backend_t( name_string_t const &table_name, rdb_context_t *rdb_context, lifetime_t<name_resolver_t const &> name_resolver, std::shared_ptr<semilattice_readwrite_view_t<auth_semilattice_metadata_t>> auth_semilattice_view, std::shared_ptr<semilattice_read_view_t<cluster_semilattice_metadata_t>> cluster_semilattice_view) : caching_cfeed_artificial_table_backend_t( table_name, rdb_context, name_resolver), m_auth_semilattice_view(std::move(auth_semilattice_view)), m_auth_subscription([this](){ notify_all(); }, m_auth_semilattice_view), m_cluster_semilattice_view(std::move(cluster_semilattice_view)) { }
OpMultiQ::~OpMultiQ() { ///////////////////////////////// // dont accept any more ops ///////////////////////////////// for (auto& grp : mOpGroups) { grp->Disable(); } ///////////////////////////////// // drain what ops we have ///////////////////////////////// drain(); ///////////////////////////////// // Signal to worker threads that we are ready to go down // Spam the worker thread semaphore until it does go down // Wait until all worker threads have exited ///////////////////////////////// mbOkToExit = true; while (int(mThreadsRunning) != 0) { notify_all(); usleep(10); } for( auto thr : mThreads ) delete thr; ///////////////////////////////// // trash the groups ///////////////////////////////// OpGroup* pgrp = nullptr; for (auto& it : mOpGroups) { delete it; } ///////////////////////////////// }
/** * Bind a host address (hello) to a hostId. * * @param peer the peer for which this is a hello * @param hello the verified (!) hello message */ static void bind_address (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello) { char *fn; struct HostEntry *host; struct GNUNET_HELLO_Message *mrg; struct GNUNET_TIME_Absolute delta; add_host_to_known_hosts (peer); host = GNUNET_CONTAINER_multihashmap_get (hostmap, &peer->hashPubKey); GNUNET_assert (host != NULL); if (host->hello == NULL) { host->hello = GNUNET_malloc (GNUNET_HELLO_size (hello)); memcpy (host->hello, hello, GNUNET_HELLO_size (hello)); } else { mrg = GNUNET_HELLO_merge (host->hello, hello); delta = GNUNET_HELLO_equals (mrg, host->hello, GNUNET_TIME_absolute_get ()); if (delta.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value) { GNUNET_free (mrg); return; } GNUNET_free (host->hello); host->hello = mrg; } fn = get_host_filename (peer); if (GNUNET_OK == GNUNET_DISK_directory_create_for_file (fn)) { if (GNUNET_SYSERR == GNUNET_DISK_fn_write (fn, host->hello, GNUNET_HELLO_size (host->hello), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn); } GNUNET_free (fn); notify_all (host); }
void Text::allocate(Canvas* c, const Allocation& a, Extension& extension) { canvas_ = c; if (! allocation_) { allocation_ = new Allocation(a); curLowerX_ = 0; curLowerY_ = 0; } else { *allocation_ = a; } curUpperX_ = curLowerX_ + allocation_->allotment(Dimension_X).span(); curUpperY_ = curLowerY_ + allocation_->allotment(Dimension_Y).span(); extension.merge(c, a); notify_all(); }
void WindowManager::read_configuration() { Fl_String buf; Fl_Config wmconf(fl_find_config_file("wmanager.conf", 0)); wmconf.set_section("TitleBar"); wmconf.read("Active color", title_active_color, fl_rgb(0,0,128)); wmconf.read("Normal color", title_normal_color, fl_rgb(192,192,192)); wmconf.read("Active color text", title_active_color_text, fl_rgb(255,255,255)); wmconf.read("Normal color text", title_normal_color_text, fl_rgb(0,0,128)); wmconf.read("Box type", Titlebar::box_type, 0); wmconf.read("Height", Titlebar::default_height, 20); wmconf.read("Text align", Titlebar::label_align, 0); Titlebar::label_align = real_align(Titlebar::label_align); wmconf.set_section("Resize"); wmconf.read("Opaque resize", Frame::do_opaque, false); wmconf.read("Animate", Frame::animate, true); wmconf.read("Animate Speed", Frame::animate_speed, 15); wmconf.set_section("Misc"); bool theme = false; wmconf.read("Use theme", theme, false); if(theme) { wmconf.read("Theme path", buf, 0); Theme::instance()->load(buf); Theme::instance()->use(true); } else { Theme::instance()->unload(); Theme::instance()->use(false); } notify_all(); read_hotkeys_configuration(); }
void Scheduler::notify_task_completion( PhysicalTaskIdentifier physical_task_id) { M3BP_SCHEDULER_TRACE << physical_task_id.identifier(); std::vector<PhysicalTaskIdentifier> successors; { std::lock_guard<std::mutex> lock(m_physical_graph_mutex); auto it = m_vertices.find(physical_task_id); assert(it != m_vertices.end()); successors = std::move(it->second->successors); m_vertices.erase(it); } for(const auto &succ_id : successors){ decrement_predecessor_count(succ_id); } const auto remains = --m_unfinished_task_count; if(remains == 0){ notify_all(); } }
/** * Add a host to the list. * * @param identity the identity of the host */ static void add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity) { struct HostEntry *entry; char *fn; entry = GNUNET_CONTAINER_multihashmap_get (hostmap, &identity->hashPubKey); if (entry != NULL) return; GNUNET_STATISTICS_update (stats, gettext_noop ("# peers known"), 1, GNUNET_NO); entry = GNUNET_malloc (sizeof (struct HostEntry)); entry->identity = *identity; GNUNET_CONTAINER_multihashmap_put (hostmap, &identity->hashPubKey, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); fn = get_host_filename (identity); entry->hello = read_host_file (fn); GNUNET_free (fn); notify_all (entry); }
s32 sys_event_flag_set(u32 id, u64 bitptn) { sys_event_flag.Log("sys_event_flag_set(id=0x%x, bitptn=0x%llx)", id, bitptn); LV2_LOCK; const auto eflag = idm::get<lv2_event_flag_t>(id); if (!eflag) { return CELL_ESRCH; } if (bitptn && ~eflag->pattern.fetch_or(bitptn) & bitptn) { eflag->notify_all(lv2_lock); } return CELL_OK; }
void close_sock(t_socket *sock, int i) { notify_all(sock, sock->pseudo[i], 2); write(1, sock->pseudo[i], my_strlen(sock->pseudo[i])); write(1, " has quit\n", 10); close(sock->cli_sock[i]); sock->cli_sock[i] = 0; #ifdef DEBUG printf("indexed:%d\n", i); #endif if (sock->pseudo[i] == NULL) write(1, "NULLED\n", 7); remove_pseudoc(sock->pseudo, sock->pseudo[i]); while (i + 1 < MAX_CLIENTS) { sock->cli_sock[i] = sock->cli_sock[i + 1]; ++i; } write(1, "closeSockEnded\n", 15); }
void Text::eraseLine() { if (insertion_.line_ < text_->Height()) { int oldWidth = text_->Width(); int index0 = text_->LineIndex(insertion_.line_); int index1 = text_->BeginningOfNextLine(index0); // ---- delete the text ---- text_->Delete(index0, index1 - index0); // --- check for width change ---- if (text_->Width() != oldWidth) { needWidth_ = true; notify_all(); } } insertion_.column_ = 0; repair(); damage(insertion_); repair(); }
void Text::reset() { text_->Delete(0, text_->Length()); insertion_.line_ = 0; insertion_.column_ = 0; selection_.line1(0); selection_.column1(0); selection_.line2(0); selection_.column2(0); if (textBuffer_) delete textBuffer_; textBuffer_ = 0; deannotate(); needWidth_ = false; width_ = 0; dirty(false); notify_all(); }
s32 sys_rwlock_wunlock(PPUThread& ppu, u32 rw_lock_id) { sys_rwlock.Log("sys_rwlock_wunlock(rw_lock_id=0x%x)", rw_lock_id); LV2_LOCK; const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); if (!rwlock) { return CELL_ESRCH; } if (rwlock->writer.get() != &ppu) { return CELL_EPERM; } rwlock->writer.reset(); rwlock->notify_all(lv2_lock); return CELL_OK; }
void ios_proxy::run(size_t threadNum) { assert(threadNum >= 1); boost::lock_guard<boost::mutex> lg(_runMutex); if (!_opend) { _opend = true; _runCount = 0; _runLock = new boost::asio::io_service::work(_ios); _handleList.resize(threadNum); size_t rc = 0; std::shared_ptr<boost::mutex> blockMutex(new boost::mutex); std::shared_ptr<boost::condition_variable> blockConVar(new boost::condition_variable); boost::unique_lock<boost::mutex> ul(*blockMutex); for (size_t i = 0; i < threadNum; i++) { boost::thread* newThread = new boost::thread([&, i] { try { { SetThreadPriority(GetCurrentThread(), _priority); DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &_handleList[i], 0, FALSE, DUPLICATE_SAME_ACCESS); auto lockMutex = blockMutex; auto lockConVar = blockConVar; boost::unique_lock<boost::mutex> ul(*lockMutex); if (threadNum == ++rc) { lockConVar->notify_all(); } else { lockConVar->wait(ul); } } _runCount += _ios.run(); } catch (msg_data::pool_memory_exception&) { MessageBoxA(NULL, "内存不足", NULL, NULL); exit(1); } catch (boost::exception&) { MessageBoxA(NULL, "未处理的BOOST异常", NULL, NULL); exit(2); } catch (std::exception&) { MessageBoxA(NULL, "未处理的STD异常", NULL, NULL); exit(3); } catch (std::shared_ptr<std::string> msg) { MessageBoxA(NULL, msg->c_str(), NULL, NULL); exit(4); } catch (...) { MessageBoxA(NULL, "未知异常", NULL, NULL); exit(-1); } }); _threadsID.insert(newThread->get_id()); _runThreads.add_thread(newThread); } blockConVar->wait(ul); } }
s32 sys_rwlock_wlock(PPUThread& ppu, u32 rw_lock_id, u64 timeout) { sys_rwlock.Log("sys_rwlock_wlock(rw_lock_id=0x%x, timeout=0x%llx)", rw_lock_id, timeout); const u64 start_time = get_system_time(); LV2_LOCK; const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); if (!rwlock) { return CELL_ESRCH; } if (rwlock->writer.get() == &ppu) { return CELL_EDEADLK; } if (!rwlock->readers && !rwlock->writer) { rwlock->writer = std::static_pointer_cast<CPUThread>(ppu.shared_from_this()); return CELL_OK; } // add waiter; protocol is ignored in current implementation sleep_queue_entry_t waiter(ppu, rwlock->wsq); while (!ppu.unsignal()) { CHECK_EMU_STATUS; if (timeout) { const u64 passed = get_system_time() - start_time; if (passed >= timeout) { // if the last waiter quit the writer sleep queue, readers must acquire the lock if (!rwlock->writer && rwlock->wsq.size() == 1) { if (rwlock->wsq.front().get() != &ppu) { throw EXCEPTION("Unexpected"); } rwlock->wsq.clear(); rwlock->notify_all(lv2_lock); } return CELL_ETIMEDOUT; } ppu.cv.wait_for(lv2_lock, std::chrono::microseconds(timeout - passed)); } else { ppu.cv.wait(lv2_lock); } } if (rwlock->readers || rwlock->writer.get() != &ppu) { throw EXCEPTION("Unexpected"); } return CELL_OK; }
/* * Called from erl_process.c. */ void erts_ddll_proc_dead(Process *p, ErtsProcLocks plocks) { erts_driver_t *drv; erts_proc_unlock(p, plocks); lock_drv_list(); drv = driver_list; while (drv != NULL) { if (drv->handle != NULL && drv->handle->status != ERL_DE_PERMANENT) { DE_ProcEntry **pe = &(drv->handle->procs); int kill_ports = (drv->handle->flags & ERL_DE_FL_KILL_PORTS); int left = 0; while ((*pe) != NULL) { if ((*pe)->proc == p) { DE_ProcEntry *r = *pe; *pe = r->next; if (!(r->flags & ERL_DE_FL_DEREFERENCED) && r->awaiting_status == ERL_DE_PROC_LOADED) { erts_ddll_dereference_driver(drv->handle); } erts_free(ERTS_ALC_T_DDLL_PROCESS, (void *) r); } else { if ((*pe)->awaiting_status == ERL_DE_PROC_LOADED) { ++left; } pe = &((*pe)->next); } } if (!left) { DE_Handle *dh = drv->handle; if (dh->status == ERL_DE_RELOAD || dh->status == ERL_DE_FORCE_RELOAD) { notify_all(dh, drv->name, ERL_DE_PROC_AWAIT_LOAD, am_DOWN, am_load_cancelled); erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_full_path); erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_driver_name); dh->reload_full_path = dh->reload_driver_name = NULL; dh->reload_flags = 0; } dh->status = ERL_DE_UNLOAD; } if (!left && erts_atomic32_read_nob(&drv->handle->port_count) > 0) { if (kill_ports) { DE_Handle *dh = drv->handle; erts_ddll_reference_driver(dh); dh->status = ERL_DE_FORCE_UNLOAD; unlock_drv_list(); kill_ports_driver_unloaded(dh); lock_drv_list(); /* Needed for future list operations */ drv = drv->next; /* before allowing destruction */ erts_ddll_dereference_driver(dh); } else { drv = drv->next; } } else { drv = drv->next; } } else { drv = drv->next; } } unlock_drv_list(); erts_proc_lock(p, plocks); }
/* You have to have loaded the driver and the pid state is LOADED or AWAIT_LOAD. You will be removed from the list regardless of driver state. If the driver is loaded by someone else to, return is {ok, pending_process} If the driver is loaded but locked by a port, return is {ok, pending_driver} If the driver is loaded and free to unload (you're the last holding it) {ok, unloaded} If it's not loaded or not loaded by you {error, not_loaded} or {error, not_loaded_by_you} Internally, if its in state UNLOADING, just return {ok, pending_driver} and remove/decrement this pid (which should be an LOADED tagged one). If the state is RELOADING, this pid should be in list as LOADED tagged, only AWAIT_LOAD would be possible but not allowed for unloading, remove it and, if the last LOADED tagged, change from RELOAD to UNLOAD and notify any AWAIT_LOAD-waiters with {'DOWN', ref(), driver, name(), load_cancelled} If the driver made itself permanent, {'UP', ref(), driver, name(), permanent} */ Eterm erl_ddll_try_unload_2(BIF_ALIST_2) { Eterm name_term = BIF_ARG_1; Eterm options = BIF_ARG_2; char *name = NULL; Eterm ok_term = NIL; Eterm soft_error_term = NIL; erts_driver_t *drv; DE_Handle *dh; DE_ProcEntry *pe; Eterm *hp; Eterm t; int monitor = 0; Eterm l; int kill_ports = 0; erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); for(l = options; is_list(l); l = CDR(list_val(l))) { Eterm opt = CAR(list_val(l)); Eterm *tp; if (is_not_tuple(opt)) { if (opt == am_kill_ports) { kill_ports = 1; continue; } else { goto error; } } tp = tuple_val(opt); if (*tp != make_arityval(2) || tp[1] != am_monitor) { goto error; } if (tp[2] == am_pending_driver) { monitor = 1; } else if (tp[2] == am_pending) { monitor = 2; } else { goto error; } } if (is_not_nil(l)) { goto error; } if ((name = pick_list_or_atom(name_term)) == NULL) { goto error; } lock_drv_list(); if ((drv = lookup_driver(name)) == NULL) { soft_error_term = am_not_loaded; goto soft_error; } if (drv->handle == NULL) { soft_error_term = am_linked_in_driver; goto soft_error; } else if (drv->handle->status == ERL_DE_PERMANENT) { soft_error_term = am_permanent; goto soft_error; } dh = drv->handle; if (dh->flags & ERL_DE_FL_KILL_PORTS) { kill_ports = 1; } if ((pe = find_proc_entry(dh, BIF_P, ERL_DE_PROC_LOADED)) == NULL) { if (num_procs(dh, ERL_DE_PROC_LOADED) > 0) { soft_error_term = am_not_loaded_by_this_process; goto soft_error; } } else { remove_proc_entry(dh, pe); if (!(pe->flags & ERL_DE_FL_DEREFERENCED)) { erts_ddll_dereference_driver(dh); } erts_free(ERTS_ALC_T_DDLL_PROCESS, pe); } if (num_procs(dh, ERL_DE_PROC_LOADED) > 0) { ok_term = am_pending_process; --monitor; goto done; } if (dh->status == ERL_DE_RELOAD || dh->status == ERL_DE_FORCE_RELOAD) { notify_all(dh, drv->name, ERL_DE_PROC_AWAIT_LOAD, am_DOWN, am_load_cancelled); erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_full_path); erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_driver_name); dh->reload_full_path = dh->reload_driver_name = NULL; dh->reload_flags = 0; } if (erts_atomic32_read_nob(&dh->port_count) > 0) { ++kill_ports; } dh->status = ERL_DE_UNLOAD; ok_term = am_pending_driver; done: assert_drv_list_rwlocked(); if (kill_ports > 1) { /* Avoid closing the driver by referencing it */ erts_ddll_reference_driver(dh); dh->status = ERL_DE_FORCE_UNLOAD; unlock_drv_list(); kill_ports_driver_unloaded(dh); lock_drv_list(); erts_ddll_dereference_driver(dh); } erts_ddll_reference_driver(dh); unlock_drv_list(); erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); lock_drv_list(); erts_ddll_dereference_driver(dh); erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name); BIF_P->flags |= F_USING_DDLL; if (monitor > 0) { Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_UNLOAD); hp = HAlloc(BIF_P, 4); t = TUPLE3(hp, am_ok, ok_term, mref); } else { hp = HAlloc(BIF_P, 3); t = TUPLE2(hp, am_ok, ok_term); } if (kill_ports > 1) { ERTS_BIF_CHK_EXITED(BIF_P); /* May be exited by port killing */ } unlock_drv_list(); BIF_RET(t); soft_error: unlock_drv_list(); erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name); erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); hp = HAlloc(BIF_P, 3); t = TUPLE2(hp, am_error, soft_error_term); BIF_RET(t); error: /* No lock fiddling before going here */ assert_drv_list_not_locked(); if (name != NULL) { erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name); } erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); BIF_ERROR(BIF_P, BADARG); }
/* * Try to load. If the driver is OK, add as LOADED. If the driver is * UNLOAD, possibly change to reload and add as LOADED, * there should be no other * LOADED tagged pid's. If the driver is RELOAD then add/increment as * LOADED (should be some LOADED pid). If the driver is not present, * really load and add as LOADED {ok,loaded} {ok,pending_driver} * {error, permanent} {error,load_error()} */ BIF_RETTYPE erl_ddll_try_load_3(BIF_ALIST_3) { Eterm path_term = BIF_ARG_1; Eterm name_term = BIF_ARG_2; Eterm options = BIF_ARG_3; char *path = NULL; Sint path_len; char *name = NULL; DE_Handle *dh; erts_driver_t *drv; int res; Eterm soft_error_term = NIL; Eterm ok_term = NIL; Eterm *hp; Eterm t; int monitor = 0; int reload = 0; Eterm l; Uint flags = 0; int kill_ports = 0; int do_build_load_error = 0; int build_this_load_error = 0; int encoding; for(l = options; is_list(l); l = CDR(list_val(l))) { Eterm opt = CAR(list_val(l)); Eterm *tp; if (is_not_tuple(opt)) { goto error; } tp = tuple_val(opt); if (*tp != make_arityval(2) || is_not_atom(tp[1])) { goto error; } switch (tp[1]) { case am_driver_options: { Eterm ll; for(ll = tp[2]; is_list(ll); ll = CDR(list_val(ll))) { Eterm dopt = CAR(list_val(ll)); if (dopt == am_kill_ports) { flags |= ERL_DE_FL_KILL_PORTS; } else { goto error; } } if (is_not_nil(ll)) { goto error; } } break; case am_monitor: if (tp[2] == am_pending_driver) { monitor = 1; } else if (tp[2] == am_pending ) { monitor = 2; } else { goto error; } break; case am_reload: if (tp[2] == am_pending_driver) { reload = 1; } else if (tp[2] == am_pending ) { reload = 2; } else { goto error; } break; default: goto error; } } if (is_not_nil(l)) { goto error; } if ((name = pick_list_or_atom(name_term)) == NULL) { goto error; } encoding = erts_get_native_filename_encoding(); if (encoding == ERL_FILENAME_WIN_WCHAR) { /* Do not convert the lib name to utf-16le yet, do that in win32 specific code */ /* since lib_name is used in error messages */ encoding = ERL_FILENAME_UTF8; } path = erts_convert_filename_to_encoding(path_term, NULL, 0, ERTS_ALC_T_DDLL_TMP_BUF, 1, 0, encoding, &path_len, sys_strlen(name) + 2); /* might need path separator */ if (!path) { goto error; } ASSERT(path_len > 0 && path[path_len-1] == 0); while (--path_len > 0 && (path[path_len-1] == '\\' || path[path_len-1] == '/')) ; path[path_len++] = '/'; sys_strcpy(path+path_len,name); erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); lock_drv_list(); if ((drv = lookup_driver(name)) != NULL) { if (drv->handle == NULL) { /* static_driver */ soft_error_term = am_linked_in_driver; goto soft_error; } else { dh = drv->handle; if (dh->status == ERL_DE_OK) { int is_last = is_last_user(dh, BIF_P); if (reload == 1 && !is_last) { /*Want reload if no other users, but there are others...*/ soft_error_term = am_pending_process; goto soft_error; } if (reload != 0) { DE_ProcEntry *old; if ((dh->flags & ERL_FL_CONSISTENT_MASK) != (flags & ERL_FL_CONSISTENT_MASK)) { soft_error_term = am_inconsistent; goto soft_error; } if ((old = find_proc_entry(dh, BIF_P, ERL_DE_PROC_LOADED)) == NULL) { soft_error_term = am_not_loaded_by_this_process; goto soft_error; } else { remove_proc_entry(dh, old); erts_ddll_dereference_driver(dh); erts_free(ERTS_ALC_T_DDLL_PROCESS, old); } /* Reload requested and granted */ dereference_all_processes(dh); set_driver_reloading(dh, BIF_P, path, name, flags); if (dh->flags & ERL_DE_FL_KILL_PORTS) { kill_ports = 1; } ok_term = (reload == 1) ? am_pending_driver : am_pending_process; } else { /* Already loaded and healthy (might be by me) */ if (sys_strcmp(dh->full_path, path) || (dh->flags & ERL_FL_CONSISTENT_MASK) != (flags & ERL_FL_CONSISTENT_MASK)) { soft_error_term = am_inconsistent; goto soft_error; } add_proc_loaded(dh, BIF_P); erts_ddll_reference_driver(dh); monitor = 0; ok_term = mkatom("already_loaded"); } } else if (dh->status == ERL_DE_UNLOAD || dh->status == ERL_DE_FORCE_UNLOAD) { /* pending driver */ if (reload != 0) { soft_error_term = am_not_loaded_by_this_process; goto soft_error; } if (sys_strcmp(dh->full_path, path) || (dh->flags & ERL_FL_CONSISTENT_MASK) != (flags & ERL_FL_CONSISTENT_MASK)) { soft_error_term = am_inconsistent; goto soft_error; } dh->status = ERL_DE_OK; notify_all(dh, drv->name, ERL_DE_PROC_AWAIT_UNLOAD, am_UP, am_unload_cancelled); add_proc_loaded(dh, BIF_P); erts_ddll_reference_driver(dh); monitor = 0; ok_term = mkatom("already_loaded"); } else if (dh->status == ERL_DE_RELOAD || dh->status == ERL_DE_FORCE_RELOAD) { if (reload != 0) { soft_error_term = am_pending_reload; goto soft_error; } if (sys_strcmp(dh->reload_full_path, path) || (dh->reload_flags & ERL_FL_CONSISTENT_MASK) != (flags & ERL_FL_CONSISTENT_MASK)) { soft_error_term = am_inconsistent; goto soft_error; } /* Load of granted unload... */ /* Don't reference, will happen after reload */ add_proc_loaded_deref(dh, BIF_P); ++monitor; ok_term = am_pending_driver; } else { /* ERL_DE_PERMANENT */ soft_error_term = am_permanent; goto soft_error; } } } else { /* driver non-existing */ if (reload != 0) { soft_error_term = am_not_loaded; goto soft_error; } if ((res = load_driver_entry(&dh, path, name)) != ERL_DE_NO_ERROR) { build_this_load_error = res; do_build_load_error = 1; soft_error_term = am_undefined; goto soft_error; } else { dh->flags = flags; add_proc_loaded(dh, BIF_P); first_ddll_reference(dh); monitor = 0; ok_term = mkatom("loaded"); } } assert_drv_list_rwlocked(); if (kill_ports) { /* Avoid closing the driver by referencing it */ erts_ddll_reference_driver(dh); ASSERT(dh->status == ERL_DE_RELOAD); dh->status = ERL_DE_FORCE_RELOAD; unlock_drv_list(); kill_ports_driver_unloaded(dh); /* Dereference, eventually causing driver destruction */ lock_drv_list(); erts_ddll_dereference_driver(dh); } erts_ddll_reference_driver(dh); unlock_drv_list(); erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); lock_drv_list(); erts_ddll_dereference_driver(dh); BIF_P->flags |= F_USING_DDLL; if (monitor) { Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_LOAD); hp = HAlloc(BIF_P, 4); t = TUPLE3(hp, am_ok, ok_term, mref); } else { hp = HAlloc(BIF_P, 3); t = TUPLE2(hp, am_ok, ok_term); } unlock_drv_list(); erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path); erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name); ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P)); BIF_RET(t); soft_error: unlock_drv_list(); erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); if (do_build_load_error) { soft_error_term = build_load_error(BIF_P, build_this_load_error); } hp = HAlloc(BIF_P, 3); t = TUPLE2(hp, am_error, soft_error_term); erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path); erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name); ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P)); BIF_RET(t); error: assert_drv_list_not_locked(); ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P)); if (path != NULL) { erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path); } if (name != NULL) { erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name); } BIF_ERROR(BIF_P, BADARG); }
void notifyAll() { notify_all(); }
void SPUThread::set_ch_value(u32 ch, u32 value) { if (Ini.HLELogging.GetValue()) { LOG_NOTICE(SPU, "set_ch_value(ch=%d [%s], value=0x%x)", ch, ch < 128 ? spu_ch_name[ch] : "???", value); } switch (ch) { //case SPU_WrSRR0: // SRR0 = value & 0x3FFFC; //LSLR & ~3 // break; case SPU_WrOutIntrMbox: { if (m_type == CPU_THREAD_RAW_SPU) { std::unique_lock<std::mutex> lock(mutex, std::defer_lock); while (!ch_out_intr_mbox.try_push(value)) { CHECK_EMU_STATUS; if (is_stopped()) throw CPUThreadStop{}; if (!lock) { lock.lock(); continue; } cv.wait(lock); } int_ctrl[2].set(SPU_INT2_STAT_MAILBOX_INT); return; } else { const u8 code = value >> 24; if (code < 64) { /* ===== sys_spu_thread_send_event (used by spu_printf) ===== */ LV2_LOCK; const u8 spup = code & 63; if (!ch_out_mbox.get_count()) { throw EXCEPTION("sys_spu_thread_send_event(value=0x%x, spup=%d): Out_MBox is empty", value, spup); } if (u32 count = ch_in_mbox.get_count()) { throw EXCEPTION("sys_spu_thread_send_event(value=0x%x, spup=%d): In_MBox is not empty (count=%d)", value, spup, count); } const u32 data = ch_out_mbox.get_value(); ch_out_mbox.set_value(data, 0); if (Ini.HLELogging.GetValue()) { LOG_NOTICE(SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, value & 0x00ffffff, data); } const auto queue = this->spup[spup].lock(); if (!queue) { LOG_WARNING(SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data); return ch_in_mbox.set_values(1, CELL_ENOTCONN); // TODO: check error passing } if (queue->events.size() >= queue->size) { return ch_in_mbox.set_values(1, CELL_EBUSY); } queue->push(lv2_lock, SYS_SPU_THREAD_EVENT_USER_KEY, m_id, ((u64)spup << 32) | (value & 0x00ffffff), data); return ch_in_mbox.set_values(1, CELL_OK); } else if (code < 128) { /* ===== sys_spu_thread_throw_event ===== */ LV2_LOCK; const u8 spup = code & 63; if (!ch_out_mbox.get_count()) { throw EXCEPTION("sys_spu_thread_throw_event(value=0x%x, spup=%d): Out_MBox is empty", value, spup); } const u32 data = ch_out_mbox.get_value(); ch_out_mbox.set_value(data, 0); if (Ini.HLELogging.GetValue()) { LOG_WARNING(SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, value & 0x00ffffff, data); } const auto queue = this->spup[spup].lock(); if (!queue) { LOG_WARNING(SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (value & 0x00ffffff), data); return; } // TODO: check passing spup value if (queue->events.size() >= queue->size) { LOG_WARNING(SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (value & 0x00ffffff), data); return; } queue->push(lv2_lock, SYS_SPU_THREAD_EVENT_USER_KEY, m_id, ((u64)spup << 32) | (value & 0x00ffffff), data); return; } else if (code == 128) { /* ===== sys_event_flag_set_bit ===== */ LV2_LOCK; const u32 flag = value & 0xffffff; if (!ch_out_mbox.get_count()) { throw EXCEPTION("sys_event_flag_set_bit(value=0x%x (flag=%d)): Out_MBox is empty", value, flag); } if (u32 count = ch_in_mbox.get_count()) { throw EXCEPTION("sys_event_flag_set_bit(value=0x%x (flag=%d)): In_MBox is not empty (%d)", value, flag, count); } const u32 data = ch_out_mbox.get_value(); ch_out_mbox.set_value(data, 0); if (flag > 63) { throw EXCEPTION("sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d)): Invalid flag", data, value, flag); } if (Ini.HLELogging.GetValue()) { LOG_WARNING(SPU, "sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d))", data, value, flag); } const auto eflag = idm::get<lv2_event_flag_t>(data); if (!eflag) { return ch_in_mbox.set_values(1, CELL_ESRCH); } const u64 bitptn = 1ull << flag; if (~eflag->pattern.fetch_or(bitptn) & bitptn) { // notify if the bit was set eflag->notify_all(lv2_lock); } return ch_in_mbox.set_values(1, CELL_OK); } else if (code == 192) { /* ===== sys_event_flag_set_bit_impatient ===== */ LV2_LOCK; const u32 flag = value & 0xffffff; if (!ch_out_mbox.get_count()) { throw EXCEPTION("sys_event_flag_set_bit_impatient(value=0x%x (flag=%d)): Out_MBox is empty", value, flag); } const u32 data = ch_out_mbox.get_value(); ch_out_mbox.set_value(data, 0); if (flag > 63) { throw EXCEPTION("sys_event_flag_set_bit_impatient(id=%d, value=0x%x (flag=%d)): Invalid flag", data, value, flag); } if (Ini.HLELogging.GetValue()) { LOG_WARNING(SPU, "sys_event_flag_set_bit_impatient(id=%d, value=0x%x (flag=%d))", data, value, flag); } const auto eflag = idm::get<lv2_event_flag_t>(data); if (!eflag) { return; } const u64 bitptn = 1ull << flag; if (~eflag->pattern.fetch_or(bitptn) & bitptn) { // notify if the bit was set eflag->notify_all(lv2_lock); } return; } else { if (ch_out_mbox.get_count()) { throw EXCEPTION("SPU_WrOutIntrMbox: unknown data (value=0x%x); Out_MBox = 0x%x", value, ch_out_mbox.get_value()); } else { throw EXCEPTION("SPU_WrOutIntrMbox: unknown data (value=0x%x)", value); } } } } case SPU_WrOutMbox: { std::unique_lock<std::mutex> lock(mutex, std::defer_lock); while (!ch_out_mbox.try_push(value)) { CHECK_EMU_STATUS; if (is_stopped()) throw CPUThreadStop{}; if (!lock) { lock.lock(); continue; } cv.wait(lock); } return; } case MFC_WrTagMask: { ch_tag_mask = value; return; } case MFC_WrTagUpdate: { ch_tag_stat.set_value(ch_tag_mask); // hack return; } case MFC_LSA: { if (value >= 0x40000) { break; } ch_mfc_args.lsa = value; return; } case MFC_EAH: { ch_mfc_args.eah = value; return; } case MFC_EAL: { ch_mfc_args.eal = value; return; } case MFC_Size: { if (value > 16 * 1024) { break; } ch_mfc_args.size = (u16)value; return; } case MFC_TagID: { if (value >= 32) { break; } ch_mfc_args.tag = (u16)value; return; } case MFC_Cmd: { process_mfc_cmd(value); ch_mfc_args = {}; // clear non-persistent data return; } case MFC_WrListStallAck: { if (value >= 32) { break; } size_t processed = 0; for (size_t i = 0; i < mfc_queue.size(); i++) { if (mfc_queue[i].second.tag == value) { do_dma_list_cmd(mfc_queue[i].first, mfc_queue[i].second); mfc_queue[i].second.tag = 0xdead; processed++; } } while (processed) { for (size_t i = 0; i < mfc_queue.size(); i++) { if (mfc_queue[i].second.tag == 0xdead) { mfc_queue.erase(mfc_queue.begin() + i); processed--; break; } } } return; } case SPU_WrDec: { ch_dec_start_timestamp = get_timebased_time(); ch_dec_value = value; return; } case SPU_WrEventMask: { // detect masking events with enabled interrupt status if (value && ch_event_stat.load() & SPU_EVENT_INTR_ENABLED) { throw EXCEPTION("SPU Interrupts not implemented (mask=0x%x)", value); } // detect masking unimplemented events if (value & ~SPU_EVENT_IMPLEMENTED) { break; } ch_event_mask.store(value); return; } case SPU_WrEventAck: { if (value & ~SPU_EVENT_IMPLEMENTED) { break; } ch_event_stat &= ~value; return; } } throw EXCEPTION("Unknown/illegal channel (ch=%d [%s], value=0x%x)", ch, ch < 128 ? spu_ch_name[ch] : "???", value); }