एक मशीन के एक नंबर पर उपयोगी एक चीज मैंने पाया है एक साधारण स्टैक स्विचर। मैंने वास्तव में PIC के लिए एक नहीं लिखा है, लेकिन मुझे उम्मीद है कि दृष्टिकोण PIC18 पर ठीक काम करेगा अगर दोनों / सभी थ्रेड्स कुल 31 या उससे कम स्टैक स्तरों का उपयोग करते हैं। 8051 में, मुख्य दिनचर्या है:
_taskswitch:
xch a, SP
xch a, _altSP
xch a, SP
गीला करना
PIC पर, मैं स्टैक पॉइंटर का नाम भूल जाता हूं, लेकिन दिनचर्या कुछ इस तरह होगी:
_taskswitch:
Movlb _altSP >> 8
Movf _altSP, डब्ल्यू, बी
Movff _STKPTR, altSP
Movwf _STKPTR, सी
वापसी
अपने कार्यक्रम की शुरुआत में, एक कार्य 2 को कॉल करें () दिनचर्या जो वैकल्पिक स्टैक के पते के साथ altSP को लोड करता है (16 शायद PIC18Fxx के लिए अच्छी तरह से काम करेगा) और कार्य 2 लूप चलाता है; इस दिनचर्या को कभी वापस नहीं करना चाहिए वरना दर्दनाक मौत मर जाएगी। इसके बजाय, इसे _taskswitch को कॉल करना चाहिए जब भी वह प्राथमिक कार्य पर नियंत्रण प्राप्त करना चाहता है; प्राथमिक कार्य को तब _taskswitch को कॉल करना चाहिए, जब भी वह द्वितीयक कार्य के लिए निकलना चाहता है। अक्सर, एक प्यारा सा दिनचर्या होगा जैसे:
शून्य देरी_टी 1 (अहस्ताक्षरित छोटी घाटी)
{
करना
taskswitch ();
जबकि ((अहस्ताक्षरित लघु) (मिलीसेकंड - वाल)> 0xFF00);
}
ध्यान दें कि टास्क स्विचर के पास किसी भी 'कंडीशन के लिए प्रतीक्षा' करने का कोई साधन नहीं है; यह सब एक स्पिनवाइट का समर्थन करता है। दूसरी ओर, टास्क स्विच इतना तेज़ होता है कि एक टास्कविच () का प्रयास करते समय दूसरा कार्य एक टाइमर के समाप्त होने की प्रतीक्षा कर रहा होता है और दूसरे कार्य पर स्विच हो जाता है, टाइमर की जाँच करता है, और एक सामान्य टास्क-स्विचर की तुलना में तेज़ी से वापस स्विच करता है यह निर्धारित करेगा कि इसे टास्कस्विच करने की आवश्यकता नहीं है।
ध्यान दें कि सहकारी मल्टीटास्किंग की कुछ सीमाएं हैं, लेकिन यह उन मामलों में बहुत सारे लॉकिंग और अन्य म्यूटेक्स-संबंधित कोडों की आवश्यकता से बचा जाता है, जहां अनियंत्रित रूप से परेशान होने वाले त्वरित रूप से पुन: स्थापित किया जा सकता है।
(संपादित करें): स्वचालित चर और इस तरह के बारे में एक युगल चेतावनी:
- यदि एक रूटीन जो टास्क-स्विचिंग का उपयोग करता है, दोनों थ्रेड्स से कॉल किया जाता है, तो यह आम तौर पर रूटीन की दो प्रतियों को संकलित करने के लिए आवश्यक होगा (संभवतः एक ही स्रोत फ़ाइल को दो बार अलग-अलग # अलग-अलग बयानों के साथ # शामिल करके)। किसी भी दी गई स्रोत फ़ाइल में या तो केवल एक थ्रेड के लिए कोड होगा, या फिर उस कोड में दो बार संकलित किया जाएगा - एक बार प्रत्येक थ्रेड के लिए - इसलिए मैं मैक्रोज़ का उपयोग कर सकता हूं जैसे "#define देरी (x) delay_t1 (x)" या #define देरी (x) delay_tx (x) "इस बात पर निर्भर करता है कि मैं किस धागे का उपयोग कर रहा हूं।
- मेरा मानना है कि PIC संकलक जो किसी फ़ंक्शन को "देख नहीं सकते" कहलाते हैं, मान सकते हैं कि ऐसा फ़ंक्शन किसी भी और सभी CPU रजिस्टरों को रद्दी कर सकता है, इस प्रकार टास्क-स्विच रूटीन में किसी भी रजिस्टर को बचाने की आवश्यकता से बचना [की तुलना में एक अच्छा लाभ] प्रीमेप्टिव मल्टीटास्किंग]। किसी भी अन्य सीपीयू के लिए समान कार्य स्विचर पर विचार करने वाले को उपयोग में रजिस्टर सम्मेलनों के बारे में पता होना चाहिए। एक कार्य स्विच से पहले रजिस्टर करना और बाद में उन्हें पॉप करना, चीजों की देखभाल का एक आसान तरीका है, पर्याप्त स्टैक स्थान मौजूद है।
सहकारी मल्टीटास्किंग किसी को लॉकिंग और इस तरह के मुद्दों से पूरी तरह से बचने की अनुमति नहीं देता है, लेकिन यह वास्तव में चीजों को बहुत सरल करता है। उदाहरण के लिए, एक कॉम्पैक्ट कचरा कलेक्टर के साथ एक प्रारंभिक आरटीओएस में, वस्तुओं को पिन करने की अनुमति देना आवश्यक है। सहकारी स्विचर का उपयोग करते समय, यह आवश्यक नहीं है कि कोड मान लेता है कि जीसी ऑब्जेक्ट किसी भी समय टास्कस्विच () कह सकते हैं। एक कॉम्पैक्टिंग कलेक्टर जिसे पिन किए गए ऑब्जेक्ट के बारे में चिंता करने की ज़रूरत नहीं है, जो एक से अधिक सरल हो सकता है।