20 Ekim 2014 Pazartesi

ACE_Thread_Manager ile yeni thread yaratmak

Not : Bu yazı ile ilgili olarak pthread_self() ile gettid() arasındaki fark başlıklı yazıya göz atabilirsiniz.
Not : Posix ile yeni thred yaratmak için pthread_create() metodunu kullanmak gerekir. Bu metod <errno.h> dosyasında tanımlı olan sonuçlardan birini döner. pthread_create Linux altında clone sistem çağrısını çağırır ve aşağıdaki gibi byarakları kullanır.

CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID

ACE_Thread_Manager

ACE_Thread_Manager ile yeni thread yaratmak çok kolay. Ancak spawn veya spawn_n metodlarını kullanırken verilen THR_NEW_LWP bitinin ne işe yaradığını pek anlayamamıştım.

Konuyu anlamak için önce Multithreading modellerine bakmak lazım. Bütün threadler kernel (çekirdek) tarafından yönetilirler. Bazı thread modelleri kernel içindeki verimliliği artırmak için değişik modelleri denemişlerdir.

Many To One (Çoktan Bire) Modeli

Bu kullanım şeklinde user space içinde bir çok thread açılsa bile kernel (çekirdek) içinde sadece bir thread açılıyor.
Aşağıdaki şekili buradan aldım ve durumu gösteriyor. Eskiden Java 1.1 zamanında green thread'ler de böyle çalışıyordu.


Bu modelin dezavantajlarından birisi, eğer bir thread I/O veya harhangi bir şey için (örneğin page-fault) bloke olursa diğer thread'ler de bundan etkilenip bloke oluyorlar. If one thread is busy on I/O will the entire process be blocked sorusunda benzer bir cevap görülebilir.


One To One (Birden bire) Modeli

Bu kullanım şeklinde user space içinde bir çok thread açılsa bile kernel (çekirdek) içinde sadece bir thread açılıyor. Aşağıdaki şekili buradan aldım ve durumu gösteriyor.

 Many To Many (Çoktan Çoka) Modeli
Bu kullanım şeklinde user space içinde bir çok thread açılınca kernel (çekirdek) içinde de bir çok. Aşağıdaki şekili buradan aldım ve durumu gösteriyor.

Benzer bir şekli ise buradan aldım.


 Peki hangi unix versiyonu hangi modeli kullanıyor ?

Solaris
Biraz araştırma yaptıktan sonra bu bayrağın sadece Solaris thread kütüphanesini taklit etmek için konulduğunu gördüm. Solaris threadlerini yaratırken thr_create metoduna bu bayrak geçiliyor. Solaris anladığım kadarıyla thread modeli olarak M:N (Hybrid Threading) modelini kullanıyor ve thr_create metodunun açıklamasında da yazdığı gibi :

Typically, THR_NEW_LWP adds a new LWP to the pool of LWPs running unbound threads.
Yani bu bit ile muhtemelen yeni bir kernel threadi yaratılıyor ve o da bizim user-level threadimizi çalıştırıyor.

Buradaki yazıda many-to-many modelin Solaris 9'dan önceki versiyonlarda default model olduğu yazıyor.

Bir başka yazıda ise M:N (Hybrid Threading) modelinin Solari 9'da terk edildiği bilgisini gördüm ama bunu teyit edemedim.

Linux
Ancak Linux üzerinde pthread_setconcurrency() metodu Linux User Manuel'de şöyle açıklanmış :


NOTES
       The default concurrency level is 0.

       Concurrency levels are only meaningful for M:N threading implementations, where at any moment a subset of a process's set  of  user-level  threads  may be bound to a smaller number of kernel-scheduling entities.  Setting the concurrency level allows the application to give the system a hint as to the number of kernel-scheduling entities that should be provided for efficient execution of the application.

       Both LinuxThreads and NPTL are 1:1 threading implementations, so setting the concurrency level has no meaning.  In other  words,  on  Linux  these functions merely exist for compatibility with other systems, and they have no effect on the execution of a program.
Yani Linux zaten 1:1 (Kernel-level threading) kullandığı için bu bayrağı set etmenin hiç bir faydası yok. Set edilse de edilmese de bir fark yaratmaz.

Bu arada not olarak şu bilgiyi eklemek te faydalı olacaktır sanırım. Linux üzerinde posix threadlerini kullanmak için libc (C Standart kütüphanesi) lazım.  Linux üzerindeki C standart kütüphanesi glibc'dir (GNU C Standart kütüphanesi). Bu kütüphane ise Posix threadleri için NTPL (Native Posix Thread Library) kütüphanesini kullanır. NTPL ise yukarıda da anlatıldığı gibi "Birden-Bire" modelini benimsemiştir.

Daha eski Linux sürümlerinde NTPL yerine "LinuxThreadLibrary" kütüphanesinin de kullanıldığını görebilirsiniz.

Buradaki bir sunumda Linux'un çekirdek 2.4 ile 2.6 versiyonları arasındaki threadler için kullanılan kütüphaneleri gösteren bir şekil de var.

Not: Posix threadleri işletim sisteminden daha yukarı seviyede tanımlanmış bir spesifikasyondur. Bu yüzden Posix thread'lerine verilen thread numarası ile örneğin Linux'taki thread numaraları birbirlerini tutmazlar. Sebebini anlamak için çoktan bire modeline bakmak yeterli olacaktır. Bu yüzden Linux'taki getid() metodu ile Posix'teki pthread_self() metodları farklı sayılar döndürürler.


Ancak posix threadlerine numara verme algoritmasını halen bulabilmiş değilim. Bulunca bu yazıyı güncellemeyi düşünüyorum.

Thread Priority

Yazının bütünlüğü açısından thread priority atamanın da eklenmesi gerektiğini düşünüyorum. Bu konuyla ilgili olarak Equivalent of SetThreadPriority on Linux (pthreads) başlıklı yazıya göz atılabilir. Önemli metodlar arasında sched_get_priority_max , pthread_setschedprio ve pthread_attr_getschedpolicy sayılabilir.

Hiç yorum yok:

Yorum Gönder