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.
synchronize do not have reserved words,
Monitor such as primitive as well as common sense
Provided that the operation of the thread itself to the following API are available.
| ||thread running someone else to move.|
| || thread |
| ||end a self-conversation.|
| ||self suspend a thread.|
| ||the end of the thread is to wait.|
| ||moratorium against the 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
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
"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.
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
prev a member name and its
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
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
This list is in a ring and the "threads" it easy to choose.
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
ruby is BETTER
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_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
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_scope correspond to the members are heard.
To register for storing
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.
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.
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
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
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
rb_thread_schedule () 伝えなくto the government. That's
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 (limit
wait_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見付かった.
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.
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?
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.
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.
setitimer is to call someone and say, happens to be on this list
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_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
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.
CHECK_INTS have so far appeared in many places.
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
setitimer If you have information about this Saturday. But
setitimer if there are no
How? Actually, I just saw
# 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.
rb_thread_schedule () .
In other words
THREAD_TICK (= 500) times
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 () .
ruby It's always important function is also big, and so on.
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.
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
select GANANTARA, see the statement.
ruby thread switch
select very dependent on so
select Let's just about prepared.
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".
select maximum waiting time.
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
select 見せようuse an example.
# include # include # include int main (int argc, char ** argv) ( char * buf ; 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.
Just look at the trend.
select The fifth argument
NULL because the
select calls are forever
stdin to wait for loading. The
It ended with the following
read can not wait to read it completely
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).
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
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
I have not run.
fd_set do more to synthesize
select at the same time
You can get through.
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 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
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
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
The conversation starts it might be possible. I check the
Taxed in the thread.見付かったら
select successful that the I / O or ready,
select is waiting
For instance, either.
fd_set to check the thread waiting is over
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
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-> priority
priority) / * (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
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.
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).
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
setjmp () and
longjmp () pairs in this thread to complete the
It is not.
setjmp () in the context of their own to save
longjmp () in the context of this thread is used to return. -
setjmp () /
longjmp () the link-chain that can be
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 () ,
rb_thread_restore_context () . Let's turn to look at.
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_start
th-> 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
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載せた
th-> stk_ptr of trying to copy us.
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
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.
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 (& v
th-> 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)
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.
rb_lastline_set () and
rb_backref_set () on.
$~ return. These two variables are local variables, a mere thread
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 ; 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
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.
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.