kernel/eka/kernel/sproperty.cpp
branchRCL_3
changeset 39 2bb754abd467
parent 0 a41df078684a
equal deleted inserted replaced
36:bbf8bed59bcb 39:2bb754abd467
    27 inline DProcess* CurProcess()
    27 inline DProcess* CurProcess()
    28 	{
    28 	{
    29 	return TheCurrentThread->iOwningProcess;
    29 	return TheCurrentThread->iOwningProcess;
    30 	}
    30 	}
    31 
    31 
       
    32 // Used by a thread to schedule cancelation of Subscribe request in Supervisor thread.
       
    33 class TCancelQ: public SDblQueLink
       
    34 {
       
    35 public:
       
    36     TPropertySubsRequest* iPropSubRequest;//The request to be cancelled, can be NULL
       
    37     NFastSemaphore iFSemaphore;//Semafore to be signalled by Supervisor thread after the request is cancelled.
       
    38 };
       
    39 
    32 class TProperty 
    40 class TProperty 
    33 	{
    41 	{
    34 public:
    42 public:
    35 	static TInt Init();
    43 	static TInt Init();
    36 
    44 
   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()
   898 		{
  1012 		{
   899 		NKern::UnlockSystem();
  1013 		NKern::UnlockSystem();
   900 		return KErrArgument;
  1014 		return KErrArgument;
   901 		}
  1015 		}
   902 	iValue = aValue;
  1016 	iValue = aValue;
   903 	CompleteByDfc();
  1017 	CompleteByDfc(); //This will also release system lock.
   904 	return KErrNone;
  1018 	return KErrNone;
   905 	}
  1019 	}
   906 
  1020 
   907 
  1021 
   908 #ifdef __EPOC32__
  1022 #ifdef __EPOC32__