Skip to content

Commit 9a0726c

Browse files
committed
Merge remote-tracking branch 'origin' into codedb-ffi-io
2 parents 3cbca7e + 44d5f80 commit 9a0726c

26 files changed

+573
-182
lines changed

core/fiber.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ def self.main
3434
raise PrimitiveFailure, "Fiber.main primitive failed"
3535
end
3636

37+
def self.count
38+
Rubinius.primitive :fiber_s_count
39+
raise PrimitiveFailure, "Fiber.count primitive failed"
40+
end
41+
3742
def status
3843
Rubinius.primitive :fiber_status
3944
raise PrimitiveFailure, "Fiber#status primitive failed"
@@ -49,6 +54,11 @@ def transfer(*args)
4954
raise PrimitiveFailure, "Fiber#transfer primitive failed"
5055
end
5156

57+
def dispose
58+
Rubinius.primitive :fiber_dispose
59+
raise PrimitiveFailure, "Fiber#dispose primitive failed"
60+
end
61+
5262
def alive?
5363
status != "dead"
5464
end

core/thread.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ def self.list
7979
Kernel.raise PrimitiveFailure, "Thread.list primitive failed"
8080
end
8181

82+
def self.count
83+
Rubinius.primitive :thread_count
84+
Kernel.raise PrimitiveFailure, "Thread.count primitive failed"
85+
end
86+
8287
def self.stop
8388
sleep
8489
nil

machine/builtin/fiber.cpp

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ namespace rubinius {
8787

8888
if(!vm()->suspended_p()) {
8989
std::ostringstream msg;
90-
msg << "attempt to restart non-suspended (" << vm()->transition_flag() << ") fiber";
90+
msg << "attempt to restart non-suspended ("
91+
<< vm()->fiber_transition_flag() << ") fiber";
9192
Exception::raise_fiber_error(state, msg.str().c_str());
9293
}
9394

@@ -97,8 +98,8 @@ namespace rubinius {
9798
wakeup();
9899

99100
while(vm()->suspended_p()) {
100-
std::lock_guard<std::mutex> guard(vm()->wait_mutex());
101-
vm()->wait_condition().notify_one();
101+
std::lock_guard<std::mutex> guard(vm()->fiber_wait_mutex());
102+
vm()->fiber_wait_condition().notify_one();
102103
}
103104
}
104105

@@ -107,15 +108,44 @@ namespace rubinius {
107108
}
108109
}
109110

111+
void Fiber::cancel(STATE) {
112+
{
113+
std::lock_guard<std::mutex> guard(state->vm()->thread()->fiber_mutex());
114+
115+
vm()->thread_state()->raise_fiber_cancel();
116+
117+
state->vm()->set_suspending();
118+
119+
restart_context(state->vm());
120+
wakeup();
121+
122+
while(vm()->suspended_p()) {
123+
std::lock_guard<std::mutex> guard(vm()->fiber_wait_mutex());
124+
vm()->fiber_wait_condition().notify_one();
125+
}
126+
}
127+
128+
vm()->limited_wait_for([this]{ return vm()->running_p(); });
129+
130+
// Release the canceled Fiber.
131+
state->vm()->set_suspended();
132+
133+
vm()->limited_wait_for([this]{ return vm()->zombie_p(); });
134+
135+
vm()->set_canceled();
136+
137+
state->vm()->set_running();
138+
}
139+
110140
void Fiber::suspend_and_continue(STATE) {
111141
UnmanagedPhase unmanaged(state);
112142

113143
{
114-
std::unique_lock<std::mutex> lk(vm()->wait_mutex());
144+
std::unique_lock<std::mutex> lk(vm()->fiber_wait_mutex());
115145

116146
vm()->set_suspended();
117147
while(!wakeup_p()) {
118-
vm()->wait_condition().wait(lk);
148+
vm()->fiber_wait_condition().wait(lk);
119149
}
120150
clear_wakeup();
121151
vm()->set_resuming();
@@ -137,6 +167,8 @@ namespace rubinius {
137167
Object* Fiber::return_value(STATE) {
138168
if(vm()->thread_state()->raise_reason() == cNone) {
139169
return state->vm()->thread()->fiber_value();
170+
} else if(vm()->thread_state()->raise_reason() == cFiberCancel) {
171+
return NULL;
140172
} else {
141173
invoke_context()->thread_state()->set_state(vm()->thread_state());
142174
return NULL;
@@ -177,16 +209,18 @@ namespace rubinius {
177209
vm->thread()->fiber_value(state, cNil);
178210
}
179211

180-
if(vm->fiber()->status() == eTransfer) {
181-
// restart the root Fiber
182-
vm->thread()->fiber()->invoke_context(vm);
183-
vm->thread()->fiber()->restart(state);
184-
} else {
185-
vm->fiber()->invoke_context()->fiber()->restart(state);
212+
if(vm->thread_state()->raise_reason() != cFiberCancel) {
213+
if(vm->fiber()->status() == eTransfer) {
214+
// restart the root Fiber
215+
vm->thread()->fiber()->invoke_context(vm);
216+
vm->thread()->fiber()->restart(state);
217+
} else {
218+
vm->fiber()->invoke_context()->fiber()->restart(state);
219+
}
186220
}
187221

188222
{
189-
std::lock_guard<std::mutex> guard(vm->wait_mutex());
223+
std::lock_guard<std::mutex> guard(vm->fiber_wait_mutex());
190224

191225
vm->fiber()->status(eDead);
192226
vm->set_suspended();
@@ -377,6 +411,12 @@ namespace rubinius {
377411
return return_value(state);
378412
}
379413

414+
Object* Fiber::dispose(STATE) {
415+
cancel(state);
416+
417+
return this;
418+
}
419+
380420
Object* Fiber::s_yield(STATE, Arguments& args) {
381421
Fiber* fiber = state->vm()->fiber();
382422
OnStack<1> os(state, fiber);
@@ -412,10 +452,30 @@ namespace rubinius {
412452
return state->vm()->thread()->fiber();
413453
}
414454

415-
void Fiber::finalize(STATE, Fiber* fib) {
455+
Fixnum* Fiber::s_count(STATE) {
456+
return state->shared().vm_fibers_count(state);
457+
}
458+
459+
void Fiber::finalize(STATE, Fiber* fiber) {
416460
if(state->shared().config.machine_fiber_log_finalizer.value) {
417461
logger::write("fiber: finalizer: %s, %d",
418-
fib->thread_name()->c_str(state), fib->fiber_id()->to_native());
462+
fiber->thread_name()->c_str(state), fiber->fiber_id()->to_native());
463+
}
464+
465+
if(fiber->vm()) {
466+
if(!state->shared().halting_p()) {
467+
if(!fiber->vm()->zombie_p()) {
468+
fiber->cancel(state);
469+
}
470+
}
471+
472+
if(fiber->vm()->zombie_p()) {
473+
VM::discard(state, fiber->vm());
474+
fiber->vm(NULL);
475+
} else {
476+
logger::write("fiber: finalizer: fiber not completed: %s, %d",
477+
fiber->thread_name()->c_str(state), fiber->fiber_id()->to_native());
478+
}
419479
}
420480
}
421481
}

machine/builtin/fiber.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ namespace rubinius {
9393
// Rubinius.primitive :fiber_s_main
9494
static Fiber* s_main(STATE);
9595

96+
// Rubinius.primitive :fiber_s_count
97+
static Fixnum* s_count(STATE);
98+
9699
bool root_p();
97100

98101
Status status() {
@@ -120,6 +123,7 @@ namespace rubinius {
120123

121124
void start(STATE, Arguments& args);
122125
void restart(STATE);
126+
void cancel(STATE);
123127
void suspend_and_continue(STATE);
124128

125129
// Rubinius.primitive :fiber_status
@@ -131,6 +135,9 @@ namespace rubinius {
131135
// Rubinius.primitive :fiber_transfer
132136
Object* transfer(STATE, Arguments& args);
133137

138+
// Rubinius.primitive :fiber_dispose
139+
Object* dispose(STATE);
140+
134141
public: /* TypeInfo */
135142

136143
class Info : public TypeInfo {

machine/builtin/system.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,14 @@ namespace rubinius {
206206
args[idx] = 0;
207207

208208
// If we added anything, then exec, otherwise fall through and fail.
209-
if(idx > 0) execvp(args[0], args);
209+
if(idx > 0) {
210+
for(int i = 0; i < 5; i++) {
211+
if(::execvp(args[0], args) < 0) {
212+
if(errno != EAGAIN) break;
213+
}
214+
}
215+
}
216+
210217
// If we failed, clean up the args.
211218
delete[] args;
212219
}
@@ -385,21 +392,19 @@ namespace rubinius {
385392

386393
static int fork_exec(STATE, int errors_fd) {
387394
state->vm()->thread_nexus()->waiting_phase(state->vm());
388-
std::lock_guard<std::mutex> guard(state->vm()->thread_nexus()->fork_mutex());
395+
std::lock_guard<std::mutex> guard(state->vm()->thread_nexus()->process_mutex());
389396

390397
state->shared().machine_threads()->before_fork_exec(state);
391398
state->memory()->set_interrupt();
392399

393-
ThreadNexus::LockStatus status = state->vm()->thread_nexus()->lock(state->vm());
400+
ThreadNexus::LockStatus status = state->vm()->thread_nexus()->fork_lock(state->vm());
394401

395402
// If execvp() succeeds, we'll read EOF and know.
396403
fcntl(errors_fd, F_SETFD, FD_CLOEXEC);
397404

398405
int pid = ::fork();
399406

400-
if(status == ThreadNexus::eLocked) {
401-
state->vm()->thread_nexus()->unlock();
402-
}
407+
state->vm()->thread_nexus()->fork_unlock(status);
403408

404409
if(pid == 0) {
405410
// We're in the child...
@@ -465,7 +470,11 @@ namespace rubinius {
465470
}
466471

467472
if(exe.argc()) {
468-
(void)::execvp(exe.command(), exe.argv());
473+
for(int i = 0; i < 5; i++) {
474+
if(::execvp(exe.command(), exe.argv()) < 0) {
475+
if(errno != EAGAIN) break;
476+
}
477+
}
469478
} else {
470479
exec_sh_fallback(state, exe.command(), exe.command_size());
471480
}
@@ -710,7 +719,7 @@ namespace rubinius {
710719

711720
Object* System::vm_exec(STATE, String* path, Array* args) {
712721
state->vm()->thread_nexus()->waiting_phase(state->vm());
713-
std::lock_guard<std::mutex> guard(state->vm()->thread_nexus()->exec_mutex());
722+
std::lock_guard<std::mutex> guard(state->vm()->thread_nexus()->process_mutex());
714723

715724
/* Setting up the command and arguments may raise an exception so do it
716725
* before everything else.
@@ -755,7 +764,11 @@ namespace rubinius {
755764
}
756765

757766
if(exe.argc()) {
758-
(void)::execvp(exe.command(), exe.argv());
767+
for(int i = 0; i < 5; i++) {
768+
if(::execvp(exe.command(), exe.argv()) < 0) {
769+
if(errno != EAGAIN) break;
770+
}
771+
}
759772
} else {
760773
exec_sh_fallback(state, exe.command(), exe.command_size());
761774
}
@@ -864,18 +877,16 @@ namespace rubinius {
864877
return force_as<Fixnum>(Primitives::failure());
865878
#else
866879
state->vm()->thread_nexus()->waiting_phase(state->vm());
867-
std::lock_guard<std::mutex> guard(state->vm()->thread_nexus()->fork_mutex());
880+
std::lock_guard<std::mutex> guard(state->vm()->thread_nexus()->process_mutex());
868881

869882
state->shared().machine_threads()->before_fork(state);
870883
state->memory()->set_interrupt();
871884

872-
ThreadNexus::LockStatus status = state->vm()->thread_nexus()->lock(state->vm());
885+
ThreadNexus::LockStatus status = state->vm()->thread_nexus()->fork_lock(state->vm());
873886

874887
int pid = ::fork();
875888

876-
if(status == ThreadNexus::eLocked) {
877-
state->vm()->thread_nexus()->unlock();
878-
}
889+
state->vm()->thread_nexus()->fork_unlock(status);
879890

880891
if(pid > 0) {
881892
// We're in the parent...
@@ -1731,6 +1742,9 @@ namespace rubinius {
17311742
case cThreadKill:
17321743
reason = state->symbol("thread_kill");
17331744
break;
1745+
case cFiberCancel:
1746+
reason = state->symbol("fiber_cancel");
1747+
break;
17341748
}
17351749

17361750
tuple->put(state, 0, reason);

machine/builtin/thread.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,10 @@ namespace rubinius {
112112
logger::write("thread: finalizer: %s", thread->vm()->name().c_str());
113113
}
114114

115-
thread->finalize_instance(state);
116-
}
117-
118-
void Thread::finalize_instance(STATE) {
119-
if(vm() && vm()->zombie_p()) {
120-
fiber_mutex_.std::mutex::~mutex();
121-
VM::discard(state, vm());
122-
vm(NULL);
115+
if(thread->vm() && thread->vm()->zombie_p()) {
116+
thread->fiber_mutex().std::mutex::~mutex();
117+
VM::discard(state, thread->vm());
118+
thread->vm(NULL);
123119
}
124120
}
125121

@@ -432,6 +428,10 @@ namespace rubinius {
432428
return state->shared().vm_threads(state);
433429
}
434430

431+
Fixnum* Thread::count(STATE) {
432+
return state->shared().vm_threads_count(state);
433+
}
434+
435435
Object* Thread::set_priority(STATE, Fixnum* new_priority) {
436436
priority(state, new_priority);
437437
return new_priority;

machine/builtin/thread.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ namespace rubinius {
131131
// Rubinius.primitive :thread_list
132132
static Array* list(STATE);
133133

134+
// Rubinius.primitive :thread_count
135+
static Fixnum* count(STATE);
136+
134137
public: /* Instance primitives */
135138

136139
void fork(STATE);
@@ -237,7 +240,6 @@ namespace rubinius {
237240
static Thread* create(STATE, Class* klass, VM* vm);
238241

239242
static void finalize(STATE, Thread* thread);
240-
void finalize_instance(STATE);
241243

242244
int start_thread(STATE, void* (*function)(void*));
243245
static void* run(void*);

machine/environment.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,8 @@ namespace rubinius {
546546
void Environment::halt(STATE, int exit_code) {
547547
utilities::thread::Mutex::LockGuard guard(halt_lock_);
548548

549+
state->shared().set_halting();
550+
549551
if(state->shared().config.system_log_lifetime.value) {
550552
logger::write("process: exit: %s %d %fs",
551553
shared->pid.c_str(), exit_code, shared->run_time());
@@ -562,6 +564,8 @@ namespace rubinius {
562564
shared->machine_threads()->shutdown(state);
563565
}
564566

567+
shared->finalizer()->dispose(state);
568+
565569
shared->thread_nexus()->lock(state->vm());
566570

567571
shared->finalizer()->finish(state);
@@ -743,5 +747,7 @@ namespace rubinius {
743747

744748
State main_state(vm);
745749
state->shared().start_signals(&main_state);
750+
751+
state->shared().set_running();
746752
}
747753
}

0 commit comments

Comments
 (0)