Speaking of the actual conversation with Ruby code still not be good showing I feel the hoops. It does not have much, let me introduce ICHIOU.
Thread.fork ( while true puts' forked thread ' end ) while true puts' main thread ' end
This program will do the right "forked thread"
and "main thread"
is
YAMAZENINATTE whinge in output.
But of course, make multiple threads of control in many ways than that.
Java as synchronize
do not have reserved words,
Mutex
, Queue
, Monitor
such as primitive as well as common sense
Provided that the operation of the thread itself to the following API are available.
Thread.pass | thread running someone else to move. | ||
Thread.kill (th) | thread th to shut down. | ||
Thread.exit | end a self-conversation. | ||
Thread.stop | self suspend a thread. | ||
Thread # join | the end of the thread is to wait. | ||
Thread # wakeup | moratorium against the thread. |
ruby
thread The conversation was "all move in unison," but the principle is actually a bit of時間ず It is not the one running order. Strictly speaking, multi-CPU machines in its own worker If the husband can move or two, but still more than the number of CPU thread If you still have to order動かなけれ.
That is the thread to create something for anyone to switch to let a thread I have no reason, but the method is divided into two types. And KANERUREBERUSUREDDO YUZAREBERUSUREDDO. This is neither self-の如く, Su Red kernel to make it user-level or make a difference. Kernel-level, multi-CPU to take advantage of multiple threads simultaneously move Can do.
, ruby
thread what of it has to do with this is in YUZAREBERUSUREDDO
There is.
And (thus) At the same time動けるconversations are strictly limited by just one.
A little more ruby
thread to talk about the feature. For another apparent thread
As the "preemptive (preemptive) whether" the points raised
There is.
"Topic (mechanism) is preemptive (preemptive)," he said, The thread is a thread switch to using it without having to explicitly wins The conversation switched to hand it to me. To the contrary point of view,スレッ DE can not control the timing of the switch, they said.
Meanwhile mechanism nonpreemptive threads, the thread is using it Explicit "this thread to give him the right to control it," say as long as Switch thread. Conversely standpoint, the thread is always the possibility切り替わ Find a place that is clear.
This distinction is partly because of the process, in that case it is a preemptive "great" In particular it. For example, there are bugs in some programs have fallen into an infinite loop 切り替わらなくprocess would be. That is one of the user program Go all the way to stop the entire system does, it will not meet. But I, Windows 3.1 is the basic MS-DOS, so switching process NONPURIENPU Windows 95 is KEDOMO Tib was preemptive. Thus the system is more Robust. Therefore 3.1 from Windows 95 is "great" story.
So ruby
say whether the conversations and, Ruby level is preemptive,
C level in the nonpreemptive. C code that is written off when the
The conversation is almost certain to switch to a specific timing.
Why do I have? The conversation is certainly useful, but use It also needs to be some kind of mental attitude. That is the thread that corresponds to the number and If you do not (must be MARUCHISUREDDOSEFU). In other words C LES Bell even if the preemptive use of the library, all Cマルチスレッ DE must be aware of that.
However, the reality of the C libraries are still many non-thread-safe.せっ
Struggling to extend library bishop easy to write but not required to respond to a thread
The library can be used to reduce the number of those meaningless. So C level
Nonpreemptive is, is ruby
is a reasonable choice.
ruby
nonpreemptive thread is that the C level. That is a
動いたらextent of the right to voluntarily hand off the gas to run it. Let's just runningスレッ
Is not run anymore and is thought to want. Who should run the right to pass
? Well before the first place, the thread is ruby
in any way inside
Represented by the difference and I do not know. Threads for managing
Variables and data types, let us see.
864 typedef struct thread * rb_thread_t; 865 static rb_thread_t curr_thread = 0; 866 static rb_thread_t main_thread; 7301 struct thread ( 7302 struct thread * next, * prev; (eval.c)
struct thread
is a very big piece of reasons, so I focused only important part.
So only two, but this next
and prev
a member name and its
The type rb_thread_t
because rb_thread_t
is linked to two-way link list
Is believed to be. And in fact, not just a list of two-way at both ends of GATSU
Wants to. That is the ring. This is a major point. Static
Variable main_thread
and curr_thread
also make the whole structure of data
As in Figure 1.
Figure 1: data structures to manage thread
main_thread
(the main thread) and when you start the program existed and
Of threads, or "first" thread. curr_thread
is natural
current thread
, that is currently running thread.
main_thread
value will not change, the process is running, curr_thread
is getting more value
Things change.
This list is in a ring and the "threads" it easy to choose.
Just next
I TAGURE link. That's only a certain amount all threads
Equality can be moved.
By the way, what the thread is the first place. Or, what if it switched to thread?
This is a very difficult problem. What program, and what objects, and It's similar to what we normally appropriate "feel" about what the understanding that De Sukkiri is called into question and answer. In particular, such as What is the process and thread Thousand different to what I heard and feel at a loss.
Still, it is realistic to a degree range. All you need is a real thread
Lines of context. ruby
and put it in context, so far seen
So, ruby_frame
and ruby_scope
, ruby_class
had.
Also ruby
is BETTER
NSUTAKKU on ruby_frame
entity to ensure that the extended use of library
I think the stack space from the machine stack program also co-Ruby
NTEKISUTO as necessary. And finally, CPU registers are essential.
These various elements context of a thread, which cut
The change is the thread switch is not. Or
Context switch (context switch) and say.
What remains is to switch the context of the story. ruby_scope
and
ruby_class
is easy to change. But heap space and make sure that an honest way
I do find shelter. The CPU will still manage to register. setjmp ()
use
Writeback can be saved. Therefore, both the region rb_thread_t
to
Have already done that.
7301 struct thread ( 7302 struct thread * next, * prev; 7303 jmp_buf context; 7315 struct FRAME * frame; / * ruby_frame * / 7316 struct SCOPE * scope; / * ruby_scope * / 7317 struct RVarmap * dyna_vars; / * ruby_dyna_vars * / 7318 struct BLOCK * block; / * ruby_block * / 7319 struct iter * iter; / * ruby_iter * / 7320 struct tag * tag; / * prot_tag * / 7321 VALUE klass; / * ruby_class * / 7322 VALUE wrapper; / * ruby_wrapper * / 7323 NODE * cref; / * ruby_cref * / 7324 7325 int flags; / * scope_vmode / rb_trap_immediate / raised * / 7326 7327 NODE * node; / * rb_current_node * / 7328 7329 int tracing; / * tracing * / 7330 VALUE errinfo; / * $! * / 7331 VALUE last_status; / * $? * / 7332 VALUE last_line; / * $ _ * / 7333 VALUE last_match; / * $ ~ * / 7334 7335 int safe; / * ruby_safe_level * / (eval.c)
In this way ruby_frame
and ruby_scope
correspond to the members are heard.
To register for storing jmp_buf
.
Now, the problem is a stack machine. To SURIKAERU How do I do?
Mechanisms for the most docile of the stack position (tip) to specify the points To rewrite the data directly. It is common CPU in the register. Only LES Register there may be a general register In order to secure one of the cases There, but I just do. Too lazy to the point that Let's just call me a stack pointer. Once you have to change this to another region You can stack of course. But of course this is against every CPU and OS Situation does need a transplant to ensure it is very difficult.
So ruby
violent means, quite a stack of machines and implements theすり替え
Be. If you are not stack pointer, the stack pointer to change the points at the
O's. You can fiddle with the stack directly've already GABEJIKO
REKUTA seen at the left is to do just a little change.
Stack also to keep in place struct thread
fix.
7310 int stk_len; / * stack length * / 7311 int stk_max; / * stk_ptr memory assigned * / 7312 VALUE * stk_ptr; / * * stack copy / 7313 VALUE * stk_pos; / * * stack position / (eval.c)
At least, the point is a lot to talk organized by three points.
Or to switch context,. That is the whole point of this chapter Is. The following is a passage from each of the three-point talking about using the film industry.
First, the first point, when the switch or thread. In other words, The conversation switched to what is causing it.
For example IO # gets
and IO # read
to something called a load,
I have read
And appear to be time-consuming while other threads are moving it to head
It should be a good addition. That is where change is required to enforce. The following is getc
of C Lee
Interface.
1185 int 1186 rb_getc (f) 1187 FILE * f; (1188 1189 int c; 1190 1191 if (! READ_DATA_PENDING (f)) ( 1192 rb_thread_wait_fd (fileno (f)); 1193) 1194 TRAP_BEG; 1195 c = getc (f); 1196 TRAP_END; 1197 1198 return c; 1199) (io.c)
READ_DATA_PENDING (f)
buffer contents of the file, you still have to check whether
Macros. The contents of the buffer should happen, zero latency, but動ける
, Immediately read. Because it takes time, I would check rb_thread_wait_fd ()
call.
This is the thread switching to indirect factors.
rb_thread_wait_fd ()
"indirect" and say "direct" first choice factors
. What's that? rb_thread_wait_fd ()
in a look at.
8047 void 8048 rb_thread_wait_fd (fd) 8049 int fd; (8050 8051 if (rb_thread_critical) return; 8052 if (curr_thread == curr_thread-> next) return; 8053 if (curr_thread-> status == THREAD_TO_KILL) return; 8054 8055 curr_thread-> status = THREAD_STOPPED; 8056 curr_thread-> fd = fd; 8057 curr_thread-> wait_for = WAIT_FD; 8058 rb_thread_schedule (); 8059) (eval.c)
The last line rb_thread_schedule ()
somewhere. This function is "a direct Source
Consideration. " ruby
thread implementation of core functions, and the selection of the following thread
Switching to go.
That's why this function or role of you to know what to say, if I wasスレッ De-scheduling (scheduling) have the words and know in advance From the hoops. If you're not, so I learned that you can notice from the following He said.
And in this case is simply to transfer control of other threads as well as he was stopped and the
Syscall-hooking. In addition, "read until the end" with a clear policy. So the
Requests rb_thread_schedule ()
伝えなくto the government. That's curr_thread
of
Assigned to the various member per. Why stop wait_for
, and the cause
I use the information fd
, each cart.
rb_thread_schedule ()
and the timing of the thread is known to switch, this time
On the contrary rb_thread_schedule ()
thread is a switch from point to see
That can be. So scan them, rb_thread_join ()
a Seki
The number of discovered.
8227 static int 8228 rb_thread_join (th, limit) 8229 rb_thread_t th; 8230 double limit; (8231 8243 curr_thread-> status = THREAD_STOPPED; 8244 curr_thread-> join = th; 8245 curr_thread-> wait_for = WAIT_JOIN; 8246 curr_thread-> delay = timeofday () + limit; 8247 if (limitwait_for | = WAIT_TIME; 8248 rb_thread_schedule (); (eval.c)
This function is Thread # join
of the entity, Thread # join
thread is the receiver's end SU
Of the method to wait. Certainly, if you have other threads waiting time to move
Therefore it is advised. The second reason for the switch見付かった.
In addition rb_thread_wait_for ()
is also a function rb_thread_schedule ()
has been found
Hoops. This is (Ruby's) sleep
and other entities.
8080 void 8081 rb_thread_wait_for (time) 8082 struct timeval time; (8083 8084 double date; 8124 date = timeofday () + (double) time.tv_sec + (double) time.tv_usec * 1e-6; 8125 curr_thread-> status = THREAD_STOPPED; 8126 curr_thread-> delay = date; 8127 curr_thread-> wait_for = WAIT_TIME; 8128 rb_thread_schedule (); 8129) (eval.c)
timeofday ()
right now is the time to return. And time
to add value,
date
is time to run out of time shows. This means that the
"Certain times you want to stop until" specified.
Which is more than a certain level of the Ruby operation is being conducted, resulting in cutting threads Resona, which were the cause of change. This means that this level of Ruby NONPURIEN PUTIBU have not been. This is, if you continue to wrestle with calculations. One thousand threads in the program, I would forever be in the running U. So to some extent動いたらvoluntarily abandoned the right to execute someone like yourself Must be. How much does it should not stop動いたら ? Then talk about it.
setitimer
We have no tricks, I'm asking the same feeling, but also more rb_thread_schedule ()
to
Someone called looking for him. Then見付かるThis is a strange place.
It is here.
8574 static void 8575 catch_timer (sig) 8576 int sig; (8577 8578 # if! Defined (POSIX_SIGNAL) & &! Defined (BSD_SIGNAL) 8579 signal (sig, catch_timer); 8580 # endif 8581 if (! Rb_thread_critical) ( 8582 if (rb_trap_immediate) ( 8583 rb_thread_schedule (); 8584) 8585 else rb_thread_pending = 1; 8586) 8587) (eval.c)
NANIYARA関係らしいthe signal, but the hell of it?
This function catch_timer ()
using it to try to track and
This area had been used.
8620 static VALUE 8621 rb_thread_start_0 (fn, arg, th_arg) 8622 VALUE (* fn) (); 8623 void * arg; 8624 rb_thread_t th_arg; (8625 8632 # if defined (HAVE_SETITIMER) 8633 if (! Thread_init) ( 8634 # ifdef POSIX_SIGNAL 8635 posix_signal (SIGVTALRM, catch_timer); 8636 # else 8637 signal (SIGVTALRM, catch_timer); 8638 # endif 8639 8640 thread_init = 1; 8641 rb_thread_start_timer (); 8642) 8643 # endif (eval.c)
In other words catch_timer ()
is SIGVTALRM
HANDORARASHII signal.
Here SIGVTALRM
which is or what kind of signal, it is also a problem.
This is actually a setitimer
to use the system calls and sent signals
For both sides. Thus, just before HAVE_SETITIMER
check on them.
setitimer
SET Interval TIMER is an abbreviation for a certain time each signal to
OS system calls to send convey.
But setitimer
is to call someone and say, happens to be on this list
Finally, a rb_thread_start_timer ()
.
To summarize all of the following scenario. setitimer
for a set time each CIGNA
LE sent to. It catch_timer ()
catch. So
rb_thread_schedule ()
calling thread to switch. Perfect.
However signals can occur at any time and it would be, but
C levels also said that preemptive in the water. So
catch_timer ()
look at the code again.
if (rb_trap_immediate) ( rb_thread_schedule (); ) else rb_thread_pending = 1;
rb_thread_schedule ()
's rb_trap_immediate
only when the conditions are
With. This is the point. rb_trap_immediate
is the street name "signal.
Immediately whether the process "and represents a lot of it is false. This is true
It is a single thread, I / O, while you're gone, and only a very limited period
There is. Source code is TRAP_BEG
and TRAP_END
surrounded by it.
Meanwhile it is false when the rb_thread_pending
set so that it
Let us further. The following variables are using it.
73 # if defined (HAVE_SETITIMER) & &! Defined (__BOW__) 74 EXTERN int rb_thread_pending; 75 # define CHECK_INTS do (\ 76 if (! Rb_prohibit_interrupt) (\ 77 if (rb_trap_pending) rb_trap_exec (); \ 78 if (rb_thread_pending & &! Rb_thread_critical) \ 79 rb_thread_schedule (); \ 80) \ 81) while (0) (rubysig.h)
In this way CHECK_INTS
in rb_thread_pending
checked and
rb_thread_schedule ()
. In other words SIGVTALRM
to take the
rb_thread_pending
is true, then CHECK_INTS
when I went to a thread
It is switched.
This CHECK_INTS
have so far appeared in many places.
For example rb_eval ()
and rb_call0 ()
and rb_yield_0 ()
. CHECK_INTS
on a regular
To pass it and put it does not make sense and the nature and function of important
Together.
setitimer
If you have information about this Saturday. But setitimer
if there are no
How? Actually, I just saw CHECK_INTS
- # else
's definition is the answer
.
84 EXTERN int rb_thread_tick; 85 # define THREAD_TICK 500 86 # define CHECK_INTS do (\ 87 if (! Rb_prohibit_interrupt) (\ 88 if (rb_trap_pending) rb_trap_exec (); \ 89 if (! Rb_thread_critical) (\ 90 if (rb_thread_tick - <= 0) (\ 91 rb_thread_tick = THREAD_TICK; \ 92 rb_thread_schedule (); \ 93) \ 94) \ 95) \ 96) while (0) (rubysig.h)
CHECK_INTS
to go through every time rb_thread_tick
is decreasing.
0 when rb_thread_schedule ()
.
In other words THREAD_TICK
(= 500) times CHECK_INTS
to通ったら
The conversation switched to the system.
The second point is how to switch or thread.
The decision to undertake the one hand rb_thread_schedule ()
.
rb_thread_schedule ()
ruby
It's always important function is also big, and so on.
This rb_thread_schedule ()
more than 220 lines.
Let's isolate it thoroughly.
7819 void 7820 rb_thread_schedule () (7821 7822 rb_thread_t next; / * OK * / 7823 rb_thread_t th; 7824 rb_thread_t curr; 7825 int found = 0; 7826 7827 fd_set readfds; 7828 fd_set writefds; 7829 fd_set exceptfds; 7830 struct timeval delay_tv, * delay_ptr; 7831 double delay, now; / * OK * / 7832 int n, max; 7833 int need_select = 0; 7834 int select_timeout = 0; 7835 7836 rb_thread_pending = 0; 7837 if (curr_thread == curr_thread-> next 7838 & & curr_thread-> status == THREAD_RUNNABLE) 7839 return; 7840 7841 next = 0; 7842 curr = curr_thread; / * starting thread * / 7843 7844 while (curr-> status == THREAD_KILLED) ( 7845 curr = curr-> prev; 7846) / *…… Select and prepare a variable use…… * / / *…… If necessary, a select…… * / / *…… Then decided to start a thread…… * / / *…… Context switch…… * / 8045) (eval.c)
(A) is only one thread is nothing if not immediately return to Has been. Therefore, since this story is make sure that there are multiple threads Possible premise.
(B) followed by variable initialization. while
included initialization I think.
curr
is prev
to辿っbecause the living ( status! = THREAD_KILLED
)
Is set in the last thread. Why "first" and not say,
" Curr
to start next curr
end up dealing with" a lot of the loop
Come out.
Then the select
GANANTARA, see the statement.
ruby
thread switch select
very dependent on so
The first select
Let's just about prepared.
select
select
is a certain file, ready to read and write
Call waiting for the system. This is a prototype.
int select (int max, fd_set * readset, fd_set * writeset, fd_set * exceptset, struct timeval * timeout);
fd_set
variable you want to check fd
on the set.
The first argument max
is "( fd_set
in the fd
maximum value) +1".
timeout
is select
maximum waiting time.
timeout
is NULL
If you wait indefinitely. timeout
0 then the value is also waiting for a second
But check back soon. The return value, so when you speak.
fd_set
dilate on. fd_set
the following macro operations.
fd_set set; FD_ZERO (& set) / * initialize * / FD_SET (fd, & set) / * set to add to file descriptor fd * / FD_ISSET (fd, & set) / * fd is true if you set * /
fd_set
is a typical sequence of bits, n the file descriptors
Check if they want to stand for the n-bit (Figure 2).
Figure 2: fd_set
Brief select
見せようuse an example.
# include# include # include # include int main (int argc, char ** argv) ( char * buf [1024]; fd_set readset; FD_ZERO (& readset); / * readset to initialize * / FD_SET (STDIN_FILENO, & readset); / * stdin Cart to set * / select (STDIN_FILENO + 1, & readset, NULL, NULL, NULL); read (STDIN_FILENO, buf, 1024); / * * succeed without delay / exit (0); )
The code calls the system must be assumed that the success of the
Error-checking is not done yet. FD_ZERO
→ FD_SET
→ select
.
Just look at the trend. select
The fifth argument timeout
is NULL
because the
This select
calls are forever stdin
to wait for loading. The select
is
It ended with the following read
can not wait to read it completely
. Middle print
between movements in the eyes of you know better.
In a little more detailed code examples include CD-ROM into it
Of the \ footnote ( select
code example: the accompanying CD-ROM doc / select.html
about).
select
prepare
, rb_thread_schedule ()
back to the code.
The number of waiting thread is the reason for each branch,
The content of the shows are short.
7848 again: / * Select related variable initialization * / 7849 max = -1; 7850 FD_ZERO (& readfds); 7851 FD_ZERO (& writefds); 7852 FD_ZERO (& exceptfds); 7853 delay = DELAY_INFTY; 7854 now = -1.0; 7855 7856 FOREACH_THREAD_FROM (curr, th) ( 7857 if (! Found & & th-> status <= THREAD_RUNNABLE) ( 7858 found = 1; 7859) 7860 if (th-> status! = THREAD_STOPPED) continue; 7861 if (th-> wait_for & WAIT_JOIN) ( / *…… Join waiting…… * / 7866) 7867 if (th-> wait_for & WAIT_FD) ( / *…… I / O waiting…… * / 7871) 7872 if (th-> wait_for & WAIT_SELECT) ( / *…… Select waiting…… * / 7882) 7883 if (th-> wait_for & WAIT_TIME) ( / *…… Waiting time…… * / 7899) 7900) 7901 END_FOREACH_FROM (curr, th); (eval.c)
But do not be noticeable FOREACH
or how the macro.
The two will then be defined.
7360 # define FOREACH_THREAD_FROM (f, x) x = f; do (x = x-> next; 7361 # define END_FOREACH_FROM (f, x)) while (x! = F) (eval.c)
Clearly to try to expand.
th = curr; do ( th = th-> next; ( ..... ) ) While (th! = Curr);
Thread ring list curr
haul from the last curr
end of the process,
When the variable th
using an意味らしい. Enumeration is a little Ruby
…… Reminiscent of something that is in too much imagination?
This code will return more of this strange loop subtly using select
necessary
Check the thread. We watched as select
exception of reading, writing
待てるall the time, so suddenly, I / O is waiting and waiting time select
one to integrate
I think it is. Also in the preceding paragraph did not explain select
of waiting.
Ruby library also IO.select
to have a method, C-level and
rb_thread_select ()
that are available. We select
also
I have not run. fd_set
do more to synthesize select
at the same time
You can get through.
The remaining join
just waiting. This code is ICHIOU let me see.
7861 if (th-> wait_for & WAIT_JOIN) ( 7862 if (rb_thread_dead (th-> join)) ( 7863 th-> status = THREAD_RUNNABLE; 7864 found = 1; 7865) 7866) (eval.c)
rb_thread_dead ()
meaning is obvious from the name. Arguments end of the thread
Whether the decision.
select
call
So far, select
whether you need is identified, if necessary, the fd_set
are also prepared
I have. So if necessary select
call. For example, you can start immediately
( THREAD_RUNNABLE
) there is a thread select
is not呼ばなく.
Actually we've already I / O and waiting for the end of the thread, and there is more
Might be a high priority. But the case is select
immediately
To be back, I / O is complete only if it were in check.
7904 if (need_select) ( 7905 / * delay to convert timeval. * / 7906 / * start immediately if there is a thread I / O check only do * / 7907 if (found) ( 7908 delay_tv.tv_sec = 0; 7909 delay_tv.tv_usec = 0; 7910 delay_ptr = & delay_tv; 7911) 7912 else if (delay == DELAY_INFTY) ( 7913 delay_ptr = 0; 7914) 7915 else ( 7916 delay_tv.tv_sec = delay; 7917 delay_tv.tv_usec = (delay - (double) delay_tv.tv_sec) * 1e6; 7918 delay_ptr = & delay_tv; 7919) 7920 7921 n = select (max +1, & readfds, & writefds, & exceptfds, delay_ptr); 7922 if (n <0) ( / *…… Signals such as the squeeze…… * / 7944) 7945 if (select_timeout & & n == 0) ( / *…… Timeout…… * / 7960) 7961 if (n> 0) ( / *…… End successfully…… * / 7989) 7990 / * wait some time at the end of the thread. 7991 in order to identify the threads to loop around again * / 7992 if (! Found & & delay! = DELAY_INFTY) 7993 goto again; 7994) (eval.c)
The first half of the block read in the comments.
delay
is one of the threads are then able to start until usec
So,
It timeval
to convert.
Is actually the second half select
to bring the divergent results. This code
And so long divided. If the signal to cut back in the first
YARINAOSU or errors either, so the significance of the remaining two.
select
timeout or if the waiting time select
waiting
The conversation starts it might be possible. I check the
Taxed in the thread.見付かったら THREAD_RUNNABLE
up.
select
successful that the I / O or ready, select
is waiting
For instance, either. fd_set
to check the thread waiting is over
Search.見付かったら THREAD_RUNNABLE
up.
As far as considering all information of the final decision as to start a conversation.
Bootable from the original source, such as waiting is over any RUNNABLE
in
Should be the appropriate to pick from.
7996 FOREACH_THREAD_FROM (curr, th) ( 7997 if (th-> status == THREAD_TO_KILL) (/ * (A) * / 7998 next = th; 7999 break; 8000) 8001 if (th-> status == THREAD_RUNNABLE & & th-> stk_ptr) ( 8002 if (! Next | | next-> prioritypriority) / * (B) * / 8003 next = th; 8004) 8005) 8006 END_FOREACH_FROM (curr, th); (eval.c)
(A) is now trying to end the thread if there is a priority basis Round exit in the standings.
(B) It Big likely to find out who. However priority
to consider the value SURURASHII.
Ruby is also a member of this level Thread # priority Thread # priority =
,
Change. In particular ruby
itself can be changed like that.
If at the end of next見付からなかったらthread, that is next
is
Set did not, what would it be? Already select
of the
So waiting time and I / O is waiting for one thread waiting for the end of that.
It remains that there are no other threads are only waiting, and I can start
Of threads, not the ends can not wait. In other words
Deadlock (dead lock).
Of course, this is in addition to a deadlock happen, but generallyデッドロッ
QUEUE to detect it is very difficult. In particular ruby
If the Mutex
such as
Ruby level has to be implemented in full is almost impossible to detect.
Then start the conversation is to be determined.
I / O and select
also check.
After the conversations aimed at shifting control to do just that.
But rb_thread_schedule ()
and the last thread switching codes
Clause once again begin to it.
The third point is the last thread switching,
Context switch (context switch).
This is ruby
of the most interesting conversations about it.
, rb_thread_schedule ()
go from the end.
This section is an embarrassment, so the story spread to the condensed version.
if (THREAD_SAVE_CONTEXT (curr)) ( return; ) rb_thread_restore_context (next, RESTORE_NORMAL);
THREAD_SAVE_CONTEXT ()
of the matter is
Some of its contents do not know to think about the deployment.
7619 # define THREAD_SAVE_CONTEXT (th) \ 7620 (rb_thread_save_context (th), thread_switch (setjmp ((th) -> context))) 7587 static int 7588 thread_switch (n) 7589 int n; (7590 7591 switch (n) ( 7592 case 0: 7593 return 0; 7594 case RESTORE_FATAL: 7595 JUMP_TAG (TAG_FATAL); 7596 break; 7597 case RESTORE_INTERRUPT: 7598 rb_interrupt (); 7599 break; / *…… Abnormal processing system to make…… * / 7612 case RESTORE_NORMAL: 7613 default: 7614 break; 7615) 7616 return 1; 7617) (eval.c)
In other words, he deployed three combined.
rb_thread_save_context (curr); switch (setjmp (curr-> context)) ( case 0: break; case RESTORE_FATAL: .... case RESTORE_INTERRUPT: .... / *…… Abnormal processing system…… * / case RESTORE_NORMAL: default: return; ) rb_thread_restore_context (next, RESTORE_NORMAL);
setjmp ()
returned rb_thread_restore_context ()
both
RESTORE_NORMAL
are emerging that is obviously suspicious.
rb_thread_restore_context ()
in longjmp ()
and the
setjmp ()
and longjmp ()
is expected to respond.
And from the name of the function and meaning of the imagination,
Save the current context of a thread setjmp Return the following thread context longjmp
It's the broad outline of the flow. However, care must be taken here
This is setjmp ()
and longjmp ()
pairs in this thread to complete the
It is not. setjmp ()
in the context of their own to save
Use, longjmp ()
in the context of this thread is used to return. -
Marika following setjmp ()
/ longjmp ()
the link-chain that can be
(Figure 3).
Figure 3: setjmp
chain of the backstitch
setjmp ()
/ longjmp ()
will be able to return around the CPU,
Ruby will remain in the context of the stack, stack machine.
The evacuation is rb_thread_save_context ()
,
Comeback rb_thread_restore_context ()
. Let's turn to look at.
rb_thread_save_context ()
First of all to save the context rb_thread_save_context ()
.
7539 static void 7540 rb_thread_save_context (th) 7541 rb_thread_t th; (7542 7543 VALUE * pos; 7544 int len; 7545 static VALUE tval; 7546 7547 len = ruby_stack_length (& pos); 7548 th-> stk_len = 0; 7549 th-> stk_pos = (rb_gc_stack_startth-> stk_max) ( 7552 REALLOC_N (th-> stk_ptr, VALUE, len); 7553 th-> stk_max = len; 7554) 7555 th-> stk_len = len; 7556 FLUSH_REGISTER_WINDOWS; 7557 MEMCPY (th-> stk_ptr, th-> stk_pos, VALUE, th-> stk_len); / *………… Back………… * / ) (eval.c)
In the second half th
in ruby_scope
variables such as globalまくっassigned to the single-minded.
Back in the protection of fun. The rest, here is part of the machine stack載せた
A whole th-> stk_ptr
of trying to copy us.
First ruby_stack_length ()
But the argument pos
address to write the end of the stack
Only the length of return. This value is used to determine the extent this stack the lower end of the address side
A th-> stk_ptr
set. NANIYARA branch is on the stack NOBIRU
NOBIRU bottom of the stack and from there (Figure 4).
Figure 4: NOBIRU stack on the bottom of the stack NOBIRU
Then after the th-> stk_ptr
at the memory stack can copy
. th-> stk_max
memory of the length of len
only copy.
FLUSH_REGISTER_WINDOWS
Chapter 5 of the moth - BEJIKOREKUSHON, I explained that I was better.
Stack of cache memory drop macro (assembler entities).
View the entire stack to call when you have to be sure.
rb_thread_restore_context ()
And finally to return to the conversation function,
rb_thread_restore_context ()
.
7635 static void 7636 rb_thread_restore_context (th, exit) 7637 rb_thread_t th; 7638 int exit; (7639 7640 VALUE v; 7641 static rb_thread_t tmp; 7642 static int ex; 7643 static VALUE tval; 7644 7645 if (! Th-> stk_ptr) rb_bug ( "unsaved context"); 7646 7647 if (& vth-> stk_pos) stack_extend (th, exit); 7650) 7651 else ( 7652 / * * NOBIRU machine on the stack / 7653 if (& v stk_pos + th-> stk_len) stack_extend (th, exit); 7654) / * Global variables…… Back to return * / 7677 tmp = th; 7678 ex = exit; 7679 FLUSH_REGISTER_WINDOWS; 7680 MEMCPY (tmp-> stk_pos, tmp-> stk_ptr, VALUE, tmp-> stk_len); 7681 7682 tval = rb_lastline_get (); 7683 rb_lastline_set (tmp-> last_line); 7684 tmp-> last_line = tval; 7685 tval = rb_backref_get (); 7686 rb_backref_set (tmp-> last_match); 7687 tmp-> last_match = tval; 7688 7689 longjmp (tmp-> context, ex); 5914) (eval.c)
Arguments th
to run back to the other. The core of the second half MEMCPY ()
and
longjmp ()
. MEMCPY ()
近けれbe close to the end the better. From this operation
longjmp ()
between the stack has been broken from the state.
Nevertheless, rb_lastline_set ()
and rb_backref_set ()
on.
This is $_
and $~
return. These two variables are local variables, a mere thread
Local and
Because there is a slot in one of the local variables present in so many conversations I
Be. This location is actually not to be back at it from the stack.
Local variables from the slot region alloca ()
to ensure that.
And the base is more than good thing, but simply stack them to write back and switch
At the current thread from the thread's stack is shorter in length it took,
Copy the moment just running function ( rb_thread_restore_context
) The News
Tack to override the frame. That is the argument th
contents were broken. So I
First, it should not have to have伸ばさないstack. Do you have it
The first half of stack_extend ()
.
7624 static void 7625 stack_extend (th, exit) 7626 rb_thread_t th; 7627 int exit; (7628 7629 VALUE space [1024]; 7630 7631 memset (space, 0, 1); / * prevent array from optimization * / 7632 rb_thread_restore_context (th, exit); 7633) (eval.c)
1K bytes of local variables (machine placed in the stack) to secure the stack
To extend the MURIYARI. However, as might be expected, stack_extend ()
and return
and
The stack of those stretched shrivel. So then and there
rb_thread_restore_context ()
to call back.
By the way rb_thread_restore_context ()
and the job is complete longjmp ()
call
To reach out and, once呼び出したらabsolutely will not come again. Naturally
stack_extend ()
never return calls. Thus
rb_thread_restore_context ()
, stack_extend ()
after returning from treatment
And everything else is no need to worry about.
More than ruby
thread switch implementation. There is no reason to believe are light. Mass -
malloc () realloc ()
to the mass memcpy ()
and setjmp () longjmp ()
of
NOBASU last line in order to stack the function call away. "Dead serious"
ARUMAI representation of the problem. However, the OS-dependent system calls instead of calling
Nor is it out the window assembler and Sparc related only registers. This
If portability is certainly likely.
There are other problems as well. It is the thread's stack all the same address percent Resona picked for the stack using a pointer to the code will not move It is not possible. In fact, Tcl / TkハマっIt is wonderful to have been, Ruby's Tcl / Tk interface from the main thread is out of necessity limited access You can avoid that.
Of course chemistry between native and say hi.
Only on certain native ruby
thread should try not to move
Not work. UNIX is a thread library is still overuse and abuse
Win32, and the thread is something few moves, so caution is necessary.
The original work is Copyright © 2002 - 2004 Minero AOKI.
Translations,  additions,  and graphics by C.E. Thornton
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike2.5 License.