kernel/eka/euser/epoc/arm/uc_utl.cia
changeset 201 43365a9b78a3
parent 0 a41df078684a
child 257 3e88ff8f41d5
equal deleted inserted replaced
200:73ea206103e6 201:43365a9b78a3
  1319 	asm("ldmfd	sp!, {r0,lr} ");
  1319 	asm("ldmfd	sp!, {r0,lr} ");
  1320 	asm("b		1b ");
  1320 	asm("b		1b ");
  1321 #endif
  1321 #endif
  1322 	}
  1322 	}
  1323 
  1323 
       
  1324 EXPORT_C __NAKED__ TInt RFastLock::Poll()
       
  1325 	{
       
  1326 	asm("1: ");
       
  1327 	asm("add	r0, r0, #4 ");					// point to iCount
       
  1328 
       
  1329 #ifdef __CPU_ARM_HAS_LDREX_STREX
       
  1330 	asm("2:		");
       
  1331 	LDREX(		2, 0);							// read
       
  1332 	asm("subs	r1, r2, #1 ");					// decrement
       
  1333 	asm("bcs	3f ");							// if no borrow, lock cannot be obtained so bail out
       
  1334 	STREX(		3, 1, 0);						// write
       
  1335 	asm("teq	r3, #0 ");						// success?
       
  1336 	asm("bne	2b ");							// no!
       
  1337 	asm("mov	r0, #0 ");						// lock acquired so return KErrNone
       
  1338 #ifdef __SMP__
       
  1339 	__DATA_MEMORY_BARRIER__(r3);				// need acquire barrier
       
  1340 #endif
       
  1341 	__JUMP(,	lr);
       
  1342 
       
  1343 	asm("3:		");
       
  1344 	asm("mov	r0, #%a0" : : "i" ((TInt)KErrTimedOut));	// else can't get it immediately so return KErrTimedOut
       
  1345 	__JUMP(,	lr);
       
  1346 #else	// no LDREX/STREX - ARM arch 5 CPU
       
  1347 	asm("mov	r1, #1 ");						// 'looking' value
       
  1348 	asm("swp	r1, r1, [r0] ");				// write looking value, read original
       
  1349 	asm("subs	r2, r1, #1 ");					// decrement count
       
  1350 	asm("strcc	r2, [r0] ");					// if borrow, was originally zero so write back -1 and return KErrNone
       
  1351 	asm("movcc	r0, #0 ");						// got lock - return KErrNone
       
  1352  	__JUMP(cc,	lr);
       
  1353 
       
  1354 	asm("strlt	r1, [r0] ");					// else if result<0 (i.e. wasn't looking value) write back original
       
  1355 	asm("mov	r0, #%a0" : : "i" ((TInt)KErrTimedOut));	// else can't get it immediately so return KErrTimedOut
       
  1356  	__JUMP(,	lr);
       
  1357 #endif
       
  1358 	}
       
  1359 
  1324 EXPORT_C __NAKED__ void RFastLock::Signal()
  1360 EXPORT_C __NAKED__ void RFastLock::Signal()
  1325 	{
  1361 	{
  1326 	asm("1: ");
  1362 	asm("1: ");
  1327 	asm("add	r0, r0, #4 ");					// point to iCount
  1363 	asm("add	r0, r0, #4 ");					// point to iCount
  1328 
  1364 
  1351 	asm("mov	r0, #1000 ");					// someone was looking, so wait 1ms and try again
  1387 	asm("mov	r0, #1000 ");					// someone was looking, so wait 1ms and try again
  1352 	asm("bl "	CSM_ZN4User12AfterHighResE27TTimeIntervalMicroSeconds32);
  1388 	asm("bl "	CSM_ZN4User12AfterHighResE27TTimeIntervalMicroSeconds32);
  1353 	asm("ldmfd	sp!, {r0,lr} ");
  1389 	asm("ldmfd	sp!, {r0,lr} ");
  1354 	asm("b		1b ");
  1390 	asm("b		1b ");
  1355 #endif
  1391 #endif
       
  1392 	}
       
  1393 
       
  1394 
       
  1395 /**
       
  1396 Acquire the lock, if necessary waiting up to a specified maximum amount of time
       
  1397 for it to become free.
       
  1398 
       
  1399 This function checks if the lock is currently held. If not the lock is marked
       
  1400 as held by the current thread and the call returns immediately. If the lock is
       
  1401 held by another thread the current thread will suspend until the lock becomes
       
  1402 free or until the specified timeout period has elapsed.
       
  1403 
       
  1404 @param aTimeout The timeout value in microseconds
       
  1405 
       
  1406 @return KErrNone if the lock was acquired successfully.
       
  1407         KErrTimedOut if the timeout has expired.
       
  1408         KErrGeneral if the lock is being reset, i.e the lock
       
  1409         is about to  be deleted.
       
  1410         KErrArgument if aTimeout is negative;
       
  1411         otherwise one of the other system wide error codes.
       
  1412 */
       
  1413 EXPORT_C __NAKED__ TInt RFastLock::Wait(TInt /*aTimeout*/)
       
  1414 	{
       
  1415 	asm("stmfd	sp!, {r4-r6,lr} ");
       
  1416 	asm("add	r4, r0, #4 ");					// r4->iCount
       
  1417 	asm("subs	r5, r1, #0 ");					// r5=aTimeout
       
  1418 	asm("mov	r6, #1000 ");
       
  1419 	asm("movle	r0, #%a0" : : "i" ((TInt)KErrArgument));	
       
  1420 	__CPOPRET(le, "r4-r6,");					// if aTimeout<=0 return KErrArgument
       
  1421 	asm("1:		");
       
  1422 
       
  1423 #ifdef __CPU_ARM_HAS_LDREX_STREX
       
  1424 	asm("2:		");
       
  1425 	LDREX(		2, 4);							// read
       
  1426 	asm("subs	r12, r2, #1 ");					// decrement
       
  1427 	STREX(		3, 12, 4);						// write
       
  1428 	asm("teq	r3, #0 ");						// success?
       
  1429 	asm("bne	2b ");							// no!
       
  1430 	asm("bcs	8f ");							// if no borrow from decrement, need to wait
       
  1431 #ifdef __SMP__
       
  1432 	__DATA_MEMORY_BARRIER__(r3);				// no need to wait, but still need acquire barrier
       
  1433 #endif
       
  1434 #else	// no LDREX/STREX - ARM arch 5 CPU
       
  1435 	asm("mov	r2, #1 ");						// 'looking' value
       
  1436 	asm("swp	r2, r2, [r4] ");				// write looking value, read original
       
  1437 	asm("subs	r12, r2, #1 ");					// decrement count
       
  1438 	asm("strlt	r12, [r4] ");					// if it becomes negative, no-one was looking
       
  1439 	asm("bcs	8f ");							// if no borrow, we have to wait
       
  1440 #endif
       
  1441 	asm("mov	r0, #0 ");						// return KErrNone
       
  1442 	__POPRET("r4-r6,");
       
  1443 
       
  1444 // We need to wait
       
  1445 	asm("8:		");
       
  1446 #ifndef __CPU_ARM_HAS_LDREX_STREX
       
  1447 // no LDREX/STREX - ARM arch 5 CPU
       
  1448 	asm("blt	3f ");							// if it wasn't 'looking' value, branch
       
  1449 
       
  1450 	// it was the 'looking' value, so wait a little bit
       
  1451 	asm("cmp	r5, #0 ");
       
  1452 	asm("ble	9f ");							// waited too long already, return KErrTimedOut
       
  1453 	asm("sub	r5, r5, r6 ");
       
  1454 	asm("mov	r6, #2000 ");
       
  1455 	asm("mov	r0, #1000 ");					// wait 1ms
       
  1456 	asm("cmp	r5, r0 ");
       
  1457 	asm("movlt	r5, r0 ");						// remaining time at least 1ms
       
  1458 	asm("bl "	CSM_ZN4User12AfterHighResE27TTimeIntervalMicroSeconds32);
       
  1459 	asm("b		1b ");							// try again
       
  1460 #endif
       
  1461 	asm("3:		");
       
  1462 	asm("sub	r0, r4, #4 ");					// r0=this
       
  1463 	asm("mov	r1, r5 ");						// r1=aTimeout
       
  1464 	asm("bl "	CSM_ZN10RSemaphore4WaitEi);	// try to acquire semaphore
       
  1465 	asm("cmp	r0, #%a0" : : "i" ((TInt)KErrTimedOut));
       
  1466 	__CPOPRET(ne, "r4-r6,");					// if wait didn't time out, return
       
  1467 	asm("mov	r5, #1 ");						// any further timed waits will be for minimum period
       
  1468 	
       
  1469 	// Before we can return KErrTimedOut we must increment iCount (since we
       
  1470 	// previously decremented it in anticipation of acquiring the lock.
       
  1471 	// However we must not increment iCount if it would become zero, since
       
  1472 	// the semaphore will have been signalled (to counterbalance the Wait()
       
  1473 	// which timed out and thus never happened). This would result in two
       
  1474 	// threads being able to acquire the lock simultaneously - one by
       
  1475 	// decrementing iCount from 0 to -1 without looking at the semaphore,
       
  1476 	// and the other by decrementing iCount from -1 to -2 and then absorbing
       
  1477 	// the spurious semaphore signal.
       
  1478 	//	orig = __e32_atomic_tas_ord32(&iCount, -1, 0, 1);	// don't release lock completely
       
  1479 	//	if (orig < -1)
       
  1480 	//		return KErrTimedOut;	// count corrected - don't need to touch semaphore
       
  1481 	// lock is actually free at this point, try again to claim it
       
  1482 	//	aTimeout = 1;
       
  1483 #ifdef __CPU_ARM_HAS_LDREX_STREX
       
  1484 #ifdef __SMP__
       
  1485 	__DATA_MEMORY_BARRIER_Z__(r3);
       
  1486 #endif
       
  1487 	asm("4:		");
       
  1488 	LDREX(		2, 4);							// read
       
  1489 	asm("adds	r2, r2, #1 ");					// increment
       
  1490 	asm("bge	3b ");							// if increment would make result >=0, wait again
       
  1491 	STREX(		3, 2, 4);						// write
       
  1492 	asm("teq	r3, #0 ");						// success?
       
  1493 	asm("bne	4b ");							// no!
       
  1494 #ifdef __SMP__
       
  1495 	__DATA_MEMORY_BARRIER__(r3);
       
  1496 #endif
       
  1497 #else	// no LDREX/STREX - ARM arch 5 CPU
       
  1498 	asm("mov	r2, #1 ");						// 'looking' value
       
  1499 	asm("swp	r2, r2, [r4] ");				// write looking value, read original
       
  1500 	asm("adds	r12, r2, #1 ");					// increment count
       
  1501 	asm("strlt	r12, [r4] ");					// if still negative, count now fixed, so return KErrTimedOut
       
  1502 	asm("streq	r2, [r4] ");					// else if not 'looking' value, write back original
       
  1503 	asm("bge	3b ");							// if 'looking' value or -1, wait again
       
  1504 #endif
       
  1505 	asm("9:		");
       
  1506 	asm("mov	r0, #%a0" : : "i" ((TInt)KErrTimedOut));	// return KErrTimedOut
       
  1507 	__POPRET("r4-r6,");
  1356 	}
  1508 	}
  1357 
  1509 
  1358 
  1510 
  1359 // Entry point stub to allow EKA1 binaries to be executed under EKA2
  1511 // Entry point stub to allow EKA1 binaries to be executed under EKA2
  1360 // Only called when process is first loaded
  1512 // Only called when process is first loaded