पर लिखने के दौरान पावरफेल अनुक्रम का डेडलॉक मैं वर्तमान में एआरएम कॉर्टेक्स एम 3 माइक्रोकंट्रोलर का उपयोग कर एक एम्बेडेड प्रोजेक्ट पर काम कर रहा हूं जिसमें फ्री ओएस के साथ फ्रीआरटीओएस है। कोड एक पूर्व सहयोगी द्वारा लिखा गया था और दुख की बात है कि इस परियोजना में कुछ अजीब बग हैं जिन्हें मुझे जल्द से जल्द ढूंढना और ठीक करना है।फ्लैश पेज
संक्षिप्त विवरण: डिवाइस को वाहनों में एकीकृत किया गया है और एक दूरस्थ सर्वर पर एक एकीकृत मॉडेम का उपयोग करके कुछ "विशेष" डेटा भेजता है।
मुख्य समस्या: चूंकि डिवाइस को वाहन में एकीकृत किया गया है, डिवाइस की बिजली आपूर्ति किसी भी समय खो जा सकती है। इसलिए डिवाइस "विशेष" डेटा के कुछ हिस्सों को दो आरक्षित फ़्लैश पृष्ठों पर संग्रहीत करता है। यह कोड मॉड्यूल दो फ़्लैश पृष्ठों पर एक ईप्राम इम्यूलेशन के रूप में रखा गया है (पहनने के स्तर और एक फ्लैश पेज से दूसरे डेटा स्थानांतरण के लिए)। eeprom इम्यूलेशन तथाकथित "आभासी पते" के साथ काम करता है, जहां आप वर्तमान में सक्रिय/मान्य फ़्लैश पृष्ठ पर किसी भी आकार के डेटा ब्लॉक लिख सकते हैं और उन वर्चुअल पतों का उपयोग करके इसे वापस पढ़ सकते हैं। पूर्व सहयोगी ने एप्राम इम्यूलेशन को मल्टीटास्किंग मॉड्यूल के रूप में कार्यान्वित किया, जहां आप एप्लिकेशन में प्रत्येक कार्य से फ़्लैश पृष्ठों को पढ़/लिख सकते हैं। पहली नजर में सबकुछ ठीक लगता है।
लेकिन मेरे प्रोजेक्ट मैनेजर ने मुझे बताया कि डिवाइस हमेशा कुछ खास "विशेष" डेटा खो देता है, जहां वाहन में बिजली की आपूर्ति का स्तर कुछ वोल्ट तक चला जाता है और डिवाइस डेटा को फ्लैश करने की कोशिश करता है। आम तौर पर बिजली की आपूर्ति लगभग 10-18 वोल्ट होती है, लेकिन यदि यह 7 वोल्ट से कम हो जाती है, तो डिवाइस को powerwarn
नामक एक इंटरप्ट प्राप्त होता है और यह powerfail task
नामक एक कार्य को ट्रिगर करता है। powerfail task
में सभी कार्यों की सर्वोच्च प्राथमिकता है और कुछ कॉलबैक निष्पादित करता है जहां उदा। मॉडेम बंद हो गया है और जहां फ़्लैश पेज में "विशेष" डेटा संग्रहीत किया जाता है। मैं कोड समझने की कोशिश की और दिन/सप्ताह के लिए डिबग और अब मैं काफी यकीन है कि मैं इस समस्या पाया हूँ:
उन कॉलबैक जो powerfail कार्य निष्पादित (powerfail कॉलबैक कहा जाता है) के भीतर, देखते हैं RTOS कहता है, जहां अन्य कार्यों को निलंबित कर दिया जाता है। लेकिन दुर्भाग्य से उन प्रस्तावित कार्य में पावरवार्न इंटरप्ट प्राप्त होने से ठीक पहले एक अधूरा EEPROM_WriteBlock()
कॉल भी हो सकता है। इसलिए पावरफेल कार्य कॉलबैक निष्पादित करता है और कॉलबैक में से एक में EE_WriteBlock()
कॉल होता है जहां कार्य EE_WriteBlock()
में म्यूटेक्स नहीं ले सकता है क्योंकि एक अन्य कार्य (जिसे निलंबित कर दिया गया था) ने इसे पहले से ही लिया है -> डेडलॉक!
यह दिनचर्या फ्लैश के लिए डेटा लिखने के लिए है:
uint16_t
EE_WriteBlock (EE_TypeDef *EE, uint16_t VirtAddress, const void *Data, uint16_t Size)
{
.
.
xSemaphoreTakeRecursive(EE->rw_mutex, portMAX_DELAY);
/* Write the variable virtual address and value in the EEPROM */
.
.
.
xSemaphoreGiveRecursive(EE->rw_mutex);
return Status;
}
इस RTOS विशिष्ट कोड जब 'xSemaphoreTakeRecursive()' कहा जाता है:
portBASE_TYPE xQueueTakeMutexRecursive(xQueueHandle pxMutex, portTickType xBlockTime)
{
portBASE_TYPE xReturn;
/* Comments regarding mutual exclusion as per those within
xQueueGiveMutexRecursive(). */
traceTAKE_MUTEX_RECURSIVE(pxMutex);
if(pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle())
{
(pxMutex->uxRecursiveCallCount)++;
xReturn = pdPASS;
}
else
{
xReturn = xQueueGenericReceive(pxMutex, NULL, xBlockTime, pdFALSE);
/* pdPASS will only be returned if we successfully obtained the mutex,
we may have blocked to reach here. */
if(xReturn == pdPASS)
{
(pxMutex->uxRecursiveCallCount)++;
}
else
{
traceTAKE_MUTEX_RECURSIVE_FAILED(pxMutex);
}
}
return xReturn;
}
मेरे परियोजना प्रबंधक खुश है कि मैं मुझे बग मिला है लेकिन वह मुझे जितनी जल्दी हो सके एक फिक्स बनाने के लिए मजबूर करता है, लेकिन जो मैं वास्तव में चाहता हूं वह कोड का पुनर्लेखन है। शायद आप में से एक सोच सकता है, बस अन्य कार्यों के निलंबन से बचें और आप कर चुके हैं, लेकिन यह एक संभावित समाधान नहीं है, क्योंकि यह एक और बग ट्रिगर कर सकता है। क्या किसी के पास त्वरित समाधान/विचार है कि मैं इस डेडलॉक समस्या को कैसे ठीक कर सकता हूं? शायद में xTaskGetCurrentTaskHandle()
का उपयोग यह निर्धारित करने के लिए कर सकता है कि म्यूटेक्स का स्वामित्व किसके पास है और फिर यह कार्य तब नहीं चल रहा है जब कार्य अब नहीं चल रहा है।
Thx
+1 यही वही है जो मैं प्रस्तावित करता हूं। लेखन एक ही बाधा में किया जाना चाहिए, अन्य सभी स्तरों को केवल कतार अनुरोध करना चाहिए। यदि आप उन्हें प्राथमिकता देने की अनुमति भी देते हैं, तो अन्य लोगों के सामने एक "महत्वपूर्ण" अनुरोध निष्पादित किया जा सकता है। – Groo
क्षमा करें, मैं उल्लेख करना भूल गया: जब मुझे पावरवॉर्न इंटरप्ट को पावरफेल कार्यों को कॉलबैक निष्पादित करना प्रारंभ होता है, लेकिन इंटरप्ट/इंटरप्ट अक्षम होते हैं। – arge
@arge - हाँ, मैंने अनुमान लगाया :) मेरा पहला विचार था कि 'अन्य कार्यों को निलंबित न करें ताकि वे म्यूटेक्स को छोड़ दें', लेकिन यह हस्तक्षेप के साथ काम नहीं कर सकता है :(फिर मैंने बेहतर विचार के बारे में सोचा .. –