110 } |
118 } |
111 |
119 |
112 static void CompleteRequest(TPropertySubsRequest*, TInt aReason); |
120 static void CompleteRequest(TPropertySubsRequest*, TInt aReason); |
113 static void CompleteQue(SDblQue* aQue, TInt aReason); |
121 static void CompleteQue(SDblQue* aQue, TInt aReason); |
114 static void CompleteDfc(TAny* aQue); |
122 static void CompleteDfc(TAny* aQue); |
115 |
123 static void CompleteDfcByKErrPermissionDenied(TAny* aQue); |
|
124 static void CompleteDfcByKErrNotFound(TAny* aQue); |
|
125 static void CompleteCancellationQDfc(TAny* aQue); |
|
126 |
116 static TUint Hash(TUint aCategory, TUint aKey); |
127 static TUint Hash(TUint aCategory, TUint aKey); |
117 static TProperty** Lookup(TUint aCategory, TUint aKey); |
128 static TProperty** Lookup(TUint aCategory, TUint aKey); |
118 static TInt LookupOrCreate(TUint aCategory, TUint aKey, TProperty**); |
129 static TInt LookupOrCreate(TUint aCategory, TUint aKey, TProperty**); |
119 |
130 |
120 TAny* operator new(TUint aSize) __NO_THROW |
131 TAny* operator new(TUint aSize) __NO_THROW |
184 return DoCheckSetRights(aProcess); |
195 return DoCheckSetRights(aProcess); |
185 } |
196 } |
186 |
197 |
187 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__ |
198 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__ |
188 |
199 |
189 enum { KCompletionDfcPriority = 2 }; |
200 enum { KCancellationDfcPriority = 1, KCompletionDfcPriority = 2 }; |
190 static TDfc CompletionDfc; |
201 static TDfc CompletionDfc; |
191 // subscriptions to be completed by the DFC |
202 static TDfc CompletionDfcPermissionDenied; |
192 static SDblQue CompletionQue; // protected by the system lock |
203 static TDfc CompletionDfcNotFound; |
|
204 static TDfc CancellationDfc; |
|
205 |
|
206 // subscriptions to be completed by the DFCs, protected by system lock |
|
207 static SDblQue CompletionQue; // to be completed by KerrNone |
|
208 static SDblQue CompletionQuePermissionDenied; |
|
209 static SDblQue CompletionQueNotFound; |
|
210 static SDblQue CancellationQue; |
193 |
211 |
194 static DMutex* FeatureLock; ///< Order KMutexOrdPubSub |
212 static DMutex* FeatureLock; ///< Order KMutexOrdPubSub |
195 |
213 |
196 // hash table collision lists |
214 // hash table collision lists |
197 enum { KHashTableLimit = 32 }; // must be power of 2 |
215 enum { KHashTableLimit = 32 }; // must be power of 2 |
264 |
282 |
265 SDblQue iPendingQue; // pending subscriptions - protected by the system lock |
283 SDblQue iPendingQue; // pending subscriptions - protected by the system lock |
266 }; |
284 }; |
267 |
285 |
268 |
286 |
|
287 // Completion/Cancelation DFCs and their corresponding queues. |
|
288 // All subscribe requests are completed in Supervisor thread. |
269 TDfc TProperty::CompletionDfc(TProperty::CompleteDfc, &TProperty::CompletionQue, KCompletionDfcPriority); |
289 TDfc TProperty::CompletionDfc(TProperty::CompleteDfc, &TProperty::CompletionQue, KCompletionDfcPriority); |
270 SDblQue TProperty::CompletionQue; |
290 SDblQue TProperty::CompletionQue; |
|
291 |
|
292 TDfc TProperty::CompletionDfcPermissionDenied(TProperty::CompleteDfcByKErrPermissionDenied, &TProperty::CompletionQuePermissionDenied, KCompletionDfcPriority); |
|
293 SDblQue TProperty::CompletionQuePermissionDenied; |
|
294 |
|
295 TDfc TProperty::CompletionDfcNotFound(TProperty::CompleteDfcByKErrNotFound, &TProperty::CompletionQueNotFound, KCompletionDfcPriority); |
|
296 SDblQue TProperty::CompletionQueNotFound; |
|
297 |
|
298 TDfc TProperty::CancellationDfc(TProperty::CompleteCancellationQDfc, &TProperty::CancellationQue, KCancellationDfcPriority); |
|
299 SDblQue TProperty::CancellationQue; |
|
300 |
271 DMutex* TProperty::FeatureLock; |
301 DMutex* TProperty::FeatureLock; |
272 TProperty* TProperty::Table[KHashTableLimit]; |
302 TProperty* TProperty::Table[KHashTableLimit]; |
273 |
303 |
274 #ifdef __DEMAND_PAGING__ |
304 #ifdef __DEMAND_PAGING__ |
275 DMutex* TProperty::PagingLockMutex; |
305 DMutex* TProperty::PagingLockMutex; |
286 { // static |
316 { // static |
287 TInt r = Kern::MutexCreate(FeatureLock, KPubSubMutexName, KMutexOrdPubSub); |
317 TInt r = Kern::MutexCreate(FeatureLock, KPubSubMutexName, KMutexOrdPubSub); |
288 if (r != KErrNone) |
318 if (r != KErrNone) |
289 return r; |
319 return r; |
290 CompletionDfc.SetDfcQ(K::SvMsgQ); |
320 CompletionDfc.SetDfcQ(K::SvMsgQ); |
|
321 CompletionDfcPermissionDenied.SetDfcQ(K::SvMsgQ); |
|
322 CompletionDfcNotFound.SetDfcQ(K::SvMsgQ); |
|
323 CancellationDfc.SetDfcQ(K::SvMsgQ); |
291 |
324 |
292 #ifdef __DEMAND_PAGING__ |
325 #ifdef __DEMAND_PAGING__ |
293 r = Kern::MutexCreate(PagingLockMutex, KPubSubMutexName2, KMutexOrdPubSub2); |
326 r = Kern::MutexCreate(PagingLockMutex, KPubSubMutexName2, KMutexOrdPubSub2); |
294 if (r != KErrNone) |
327 if (r != KErrNone) |
295 return r; |
328 return r; |
510 // 'localCompletionQue' for entries that will be completed |
543 // 'localCompletionQue' for entries that will be completed |
511 // We move entries one by one dropping and reacquiring the system lock on each |
544 // We move entries one by one dropping and reacquiring the system lock on each |
512 // iteration; we get (move) always the first 'iPendingQue' entry until the |
545 // iteration; we get (move) always the first 'iPendingQue' entry until the |
513 // queue becomes empty. |
546 // queue becomes empty. |
514 // |
547 // |
515 SDblQue localPendingQue; // protected by the system lock |
548 |
516 SDblQue localCompletionQue; // protected by the system lock |
549 SDblQue localPendingQue; // Will hold requests with sufficient capabilities. |
|
550 TInt accessDeniedCounter = 0;// Will count requests with no sufficient capabilities. |
517 NKern::LockSystem(); |
551 NKern::LockSystem(); |
518 while (!iPendingQue.IsEmpty()) |
552 while (!iPendingQue.IsEmpty()) |
519 { |
553 { |
520 TPropertySubsRequest* subs = (TPropertySubsRequest*) iPendingQue.GetFirst(); |
554 TPropertySubsRequest* subs = (TPropertySubsRequest*) iPendingQue.GetFirst(); |
521 DProcess* process = subs->iProcess; |
555 DProcess* process = subs->iProcess; |
522 subs->iProcess = NULL; |
556 subs->iProcess = NULL; |
523 if (process && !CheckGetRights(process, __PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Subscribe to a Publish and Subscribe Property"))) |
557 if (process && !CheckGetRights(process, __PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Subscribe to a Publish and Subscribe Property"))) |
524 { // Check fails - will complete the subscription with an error |
558 { // Check fails - will complete the subscription with an error |
525 localCompletionQue.Add(subs); |
559 CompletionQuePermissionDenied.Add(subs); |
|
560 accessDeniedCounter++; |
526 } |
561 } |
527 else |
562 else |
528 { // Check OK - will leave in the pending queue |
563 { // Check OK - will leave in the pending queue |
529 localPendingQue.Add(subs); |
564 localPendingQue.Add(subs); |
530 } |
565 } |
534 iType = (TUint8) aInfo->iType; |
569 iType = (TUint8) aInfo->iType; |
535 NKern::UnlockSystem(); |
570 NKern::UnlockSystem(); |
536 // Now the property can be accessed by other threads. |
571 // Now the property can be accessed by other threads. |
537 Use(); |
572 Use(); |
538 Unlock(); |
573 Unlock(); |
539 // Now we can complete requests. |
574 |
540 CompleteQue(&localCompletionQue, KErrPermissionDenied); |
575 // Schedule DFC to complete requests of those with insufficient capabilities. |
|
576 if (accessDeniedCounter) |
|
577 CompletionDfcPermissionDenied.Enque(); |
541 return KErrNone; |
578 return KErrNone; |
542 } |
579 } |
543 |
580 |
544 // Called in CS |
581 // Called in CS |
545 TInt TProperty::Attach(TUint aCategory, TUint aKey, TProperty** aProp) |
582 TInt TProperty::Attach(TUint aCategory, TUint aKey, TProperty** aProp) |
602 // Remember that iType is the tag of iBuf and iValue union |
639 // Remember that iType is the tag of iBuf and iValue union |
603 TBuf* buf = (iType != RProperty::EInt) ? iBuf : NULL; |
640 TBuf* buf = (iType != RProperty::EInt) ? iBuf : NULL; |
604 SetNotDefined(); |
641 SetNotDefined(); |
605 // Down from here nobody can access the property value |
642 // Down from here nobody can access the property value |
606 |
643 |
607 // We don't want to complete requests holding the feature lock. |
644 // Move all pending requests to completion queue (to be completed by KErrNotFound). |
608 SDblQue localQue; |
645 TBool pendingQueEmpty = iPendingQue.IsEmpty(); |
609 localQue.MoveFrom(&iPendingQue); |
646 if(!pendingQueEmpty) |
|
647 CompletionQueNotFound.MoveFrom(&iPendingQue); |
610 |
648 |
611 NKern::UnlockSystem(); |
649 NKern::UnlockSystem(); |
612 |
650 |
613 iBuf = NULL; |
651 iBuf = NULL; |
614 iValue = 0; |
652 iValue = 0; |
615 delete buf; |
653 delete buf; |
616 Release(); |
654 Release(); |
617 // '*this' may do not exist any more |
655 // '*this' may do not exist any more |
618 Unlock(); |
656 Unlock(); |
619 // Now we can complete. |
657 |
620 CompleteQue(&localQue, KErrNotFound); |
658 // Schedule Svc Dfc to complete all requests from CompletionQueNotFound. |
|
659 if (!pendingQueEmpty) |
|
660 CompletionDfcNotFound.Enque(); |
621 return KErrNone; |
661 return KErrNone; |
622 } |
662 } |
623 |
663 |
624 // Enter feature locked. |
664 // Enter feature locked. |
625 // Return feature locked. |
665 // Return feature locked. |
659 if (defined) |
699 if (defined) |
660 { // property is defined - check access now |
700 { // property is defined - check access now |
661 aSubs->iProcess = NULL; |
701 aSubs->iProcess = NULL; |
662 if (aProcess && !CheckGetRights(aProcess,__PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Subscribe to a Publish and Subscribe Property"))) |
702 if (aProcess && !CheckGetRights(aProcess,__PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Subscribe to a Publish and Subscribe Property"))) |
663 { |
703 { |
664 NKern::ThreadEnterCS(); |
704 CompletionQuePermissionDenied.Add(aSubs); |
665 CompleteRequest(aSubs, KErrPermissionDenied); |
705 CompletionDfcPermissionDenied.Enque(SYSTEM_LOCK); |
666 NKern::ThreadLeaveCS(); |
|
667 return KErrNone; |
706 return KErrNone; |
668 } |
707 } |
669 } |
708 } |
670 else |
709 else |
671 { // will check when defined |
710 { // will check when defined |
679 // Enter system locked. |
718 // Enter system locked. |
680 // Return system unlocked. |
719 // Return system unlocked. |
681 void TProperty::Cancel(TPropertySubsRequest* aSubs) |
720 void TProperty::Cancel(TPropertySubsRequest* aSubs) |
682 { |
721 { |
683 __ASSERT_SYSTEM_LOCK; |
722 __ASSERT_SYSTEM_LOCK; |
684 if (!aSubs->iNext) |
723 |
685 { // not pending - silently return |
724 // This is set if the request is about to be completed (in SVC thread). In that case, a 'dummy' CancelationDFC |
686 NKern::UnlockSystem(); |
725 // will be scheduled here. This will just ensure that we don't return from Cancel before ongoing completion has finished. |
|
726 TBool scheduledForCompletition = (TInt)(aSubs->iProcess) & TPropertySubsRequest::KScheduledForCompletion; |
|
727 |
|
728 if (!aSubs->iNext && !scheduledForCompletition) |
|
729 { // Neither in any queue nor scheduled for completion. |
|
730 // The request is not active - silently return. |
|
731 NKern::UnlockSystem(); |
687 return; |
732 return; |
688 } |
733 } |
689 aSubs->Deque(); |
734 |
690 aSubs->iNext = NULL; |
735 if (aSubs->iNext) |
691 aSubs->iProcess = NULL; |
736 { |
692 NKern::ThreadEnterCS(); |
737 // Take it out from the current queue. It is usually pending queue of a property but could |
693 CompleteRequest(aSubs, KErrCancel); |
738 // also be one of the completion queues. |
694 NKern::ThreadLeaveCS(); |
739 aSubs->Deque(); |
|
740 aSubs->iNext = NULL; |
|
741 } |
|
742 |
|
743 // Set process to NULL (leave KScheduledForCompletion bit as it is) |
|
744 aSubs->iProcess = (DProcess*)((TInt)aSubs->iProcess & ~TPropertySubsRequest::KProcessPtrMask); |
|
745 |
|
746 if (&Kern::CurrentThread() == K::SvThread) |
|
747 { // Complete the request immediatelly if already running in supervisor thread... |
|
748 if (!scheduledForCompletition) |
|
749 CompleteRequest(aSubs, KErrCancel); //This will also release system lock. |
|
750 else |
|
751 NKern::UnlockSystem(); // Nothing to be done here. Just release system lock. |
|
752 } |
|
753 else |
|
754 { //... or schedule DFC in supervisor thread to complete the request. |
|
755 TCancelQ linkQ; |
|
756 if (!scheduledForCompletition) |
|
757 linkQ.iPropSubRequest = aSubs; // CancelationDFC will complete this request with KErrCancel. |
|
758 else |
|
759 linkQ.iPropSubRequest = NULL; // Schedule 'dummy' CancelationDFC (no request will be completed). |
|
760 linkQ.iFSemaphore.iOwningThread = NKern::CurrentThread(); |
|
761 CancellationQue.Add(&linkQ); |
|
762 CancellationDfc.Enque(SYSTEM_LOCK); // This will also release system lock. |
|
763 |
|
764 NKern::FSWait(&linkQ.iFSemaphore); // Wait for CancellationDfc to finish. |
|
765 } |
695 } |
766 } |
696 |
767 |
697 // Enter system locked. |
768 // Enter system locked. |
698 // Return system unlocked. |
769 // Return system unlocked. |
699 // Called in CS or a DFC context |
770 // Executed in supervisor thread. |
700 void TProperty::CompleteRequest(TPropertySubsRequest* aSubs, TInt aResult) |
771 void TProperty::CompleteRequest(TPropertySubsRequest* aSubs, TInt aResult) |
701 { // static |
772 { // static |
702 __ASSERT_SYSTEM_LOCK; |
773 __ASSERT_SYSTEM_LOCK; |
703 __ASSERT_CRITICAL; |
774 __PS_ASSERT(&Kern::CurrentThread() == K::SvThread); |
704 TPropertyCompleteFn fn = aSubs->iCompleteFn; |
775 TPropertyCompleteFn fn = aSubs->iCompleteFn; |
705 TAny* ptr = aSubs->iPtr; |
776 TAny* ptr = aSubs->iPtr; |
|
777 // Mark that this request is about to be completed. |
|
778 aSubs->iProcess = (DProcess*)((TInt)aSubs->iProcess | TPropertySubsRequest::KScheduledForCompletion); |
706 NKern::UnlockSystem(); |
779 NKern::UnlockSystem(); |
707 (*fn)(ptr, aResult); |
780 (*fn)(ptr, aResult); |
708 } |
781 } |
709 |
782 |
710 // Called in CS or a DFC context |
783 // Executed in supervisor thread. |
711 void TProperty::CompleteQue(SDblQue* aQue, TInt aReason) |
784 void TProperty::CompleteQue(SDblQue* aQue, TInt aReason) |
712 { // static |
785 { // static |
713 __ASSERT_CRITICAL; |
786 __PS_ASSERT(&Kern::CurrentThread() == K::SvThread); |
714 NKern::LockSystem(); |
787 NKern::LockSystem(); |
715 while (!aQue->IsEmpty()) |
788 while (!aQue->IsEmpty()) |
716 { |
789 { |
717 TPropertySubsRequest* subs = (TPropertySubsRequest*) aQue->First(); |
790 TPropertySubsRequest* subs = (TPropertySubsRequest*) aQue->First(); |
718 subs->Deque(); |
791 subs->Deque(); |
721 NKern::LockSystem(); |
794 NKern::LockSystem(); |
722 } |
795 } |
723 NKern::UnlockSystem(); |
796 NKern::UnlockSystem(); |
724 } |
797 } |
725 |
798 |
726 // Executed in DFC context |
799 // Executed in supervisor thread. Completes requests with KErrNone. |
727 void TProperty::CompleteDfc(TAny* aQue) |
800 void TProperty::CompleteDfc(TAny* aQue) |
728 { // static |
801 { // static |
729 CompleteQue((SDblQue*) aQue, KErrNone); |
802 CompleteQue((SDblQue*) aQue, KErrNone); |
|
803 } |
|
804 |
|
805 // Executed in supervisor thread. |
|
806 void TProperty::CompleteDfcByKErrPermissionDenied(TAny* aQue) |
|
807 { // static |
|
808 CompleteQue((SDblQue*) aQue, KErrPermissionDenied); |
|
809 } |
|
810 |
|
811 // Executed in supervisor thread. |
|
812 void TProperty::CompleteDfcByKErrNotFound(TAny* aQue) |
|
813 { // static |
|
814 CompleteQue((SDblQue*) aQue, KErrNotFound); |
|
815 } |
|
816 |
|
817 // Executed in supervisor thread. |
|
818 void TProperty::CompleteCancellationQDfc(TAny* aAny) |
|
819 { // static |
|
820 SDblQue* aQue = (SDblQue*)aAny; |
|
821 NKern::LockSystem(); |
|
822 while (!aQue->IsEmpty() ) |
|
823 { |
|
824 TCancelQ* first = static_cast<TCancelQ*>(aQue->First()); |
|
825 first->Deque(); |
|
826 first->iNext = NULL; |
|
827 |
|
828 if( first->iPropSubRequest) |
|
829 { |
|
830 CompleteRequest(first->iPropSubRequest, KErrCancel); // This will also release system lock. |
|
831 NKern::LockSystem(); |
|
832 } |
|
833 else |
|
834 { |
|
835 // Do not complete the request. |
|
836 // It was already just about to be completed when Cancel request was issued. |
|
837 // As all complitions (this method included) run is Svc thread, we can here be sure that |
|
838 // the request is now completed. |
|
839 NKern::FlashSystem(); // Preemption point |
|
840 } |
|
841 NKern::FSSignal( &first->iFSemaphore ); // Issue the signal that the request is now completed. |
|
842 } |
|
843 NKern::UnlockSystem(); |
730 } |
844 } |
731 |
845 |
732 // Enter system locked. |
846 // Enter system locked. |
733 // Return system unlocked. |
847 // Return system unlocked. |
734 void TProperty::CompleteByDfc() |
848 void TProperty::CompleteByDfc() |