mem_palmos.c
Upload User: wstnjxml
Upload Date: 2014-04-03
Package Size: 7248k
Code Size: 13k
Category:

Windows CE

Development Platform:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: mem_palmos.c 543 2006-01-07 22:06:24Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common.h"
  24. //#define TRACKMEMORY
  25. #if defined(TARGET_PALMOS)
  26. #define MIN_DYNAMIC_LIMIT 32768
  27. #define TRY_DYNAMIC 3*1024*1024
  28. #define FTRID_MIN 4096
  29. #define FTRID_MAX 16384
  30. #define MAX_CACHE 32768
  31. #include "pace.h"
  32. extern SysAppInfoPtr SysGetAppInfo(SysAppInfoPtr *uiAppPP, SysAppInfoPtr* actionCodeAppPP);
  33. #ifdef HAVE_PALMONE_SDK
  34. #include <68K/System/PmPalmOSNVFS.h>
  35. #endif
  36. static block FlushCache = {NULL};
  37. static int OutOfMemory = 0;
  38. static UInt16 StorageId = 1;
  39. void free(void *p)
  40. {
  41. if (p)
  42. {
  43. #ifdef TRACKMEMORY
  44. int q = AvailMemory();
  45. #endif
  46. MemPtrFree(p);
  47. #ifdef TRACKMEMORY
  48. DebugMessage("%08x free:%d %d",p,AvailMemory(),q-AvailMemory());
  49. #endif
  50. }
  51. }
  52. void EnableOutOfMemory()
  53. {
  54. OutOfMemory--;
  55. }
  56. void DisableOutOfMemory()
  57. {
  58. OutOfMemory++;
  59. }
  60. void ShowOutOfMemory()
  61. {
  62. if (OutOfMemory<=0)
  63. {
  64. RectangleType r;
  65. Coord Width;
  66. Coord Height;
  67. const tchar_t* s = LangStr(ERR_ID,ERR_OUT_OF_MEMORY);
  68. WinHandle Old = WinSetDrawWindow(WinGetDisplayWindow());
  69. WinGetDisplayExtent(&Width, &Height);
  70. if (Width<60)
  71. Width=60;
  72. r.topLeft.x = (Coord)(Width-80);
  73. r.topLeft.y = 16;
  74. r.extent.x = 79;
  75. r.extent.y = 15; 
  76. WinEraseRectangle(&r, 0);
  77. WinDrawChars(s, (Int16)strlen(s), (Coord)(r.topLeft.x+1), (Coord)(r.topLeft.y+1));
  78. if (Old)
  79. WinSetDrawWindow(Old);
  80. }
  81. }
  82. void* malloc(size_t n)
  83. {
  84. #ifdef TRACKMEMORY
  85. int q = AvailMemory();
  86. #endif
  87. void *p = NULL;
  88. if (n)
  89. {
  90. do
  91. {
  92. if ((size_t)AvailMemory()>MIN_DYNAMIC_LIMIT+n)
  93. p = MemGluePtrNew(n);
  94. } while (!p && NodeHibernate());
  95. if (!p)
  96. {
  97. //DebugMessage("malloc %d %d",n,AvailMemory());
  98. ShowOutOfMemory();
  99. }
  100. }
  101. #ifdef TRACKMEMORY
  102. DebugMessage("%08x malloc:%d %d %d",p,n,q,q-AvailMemory());
  103. if (n>1024)
  104. ThreadSleep(300);
  105. #endif
  106. return p;
  107. }
  108. void* realloc(void* p,size_t n)
  109. {
  110. #ifdef TRACKMEMORY
  111. int q = AvailMemory();
  112. #endif
  113. if (!p)
  114. return malloc(n);
  115. else
  116. if (!n)
  117. {
  118. MemPtrFree(p);
  119. #ifdef TRACKMEMORY
  120. DebugMessage("%08x free:%d %d",p,AvailMemory(),q-AvailMemory());
  121. #endif
  122. return NULL;
  123. }
  124. else
  125. if (MemPtrResize(p,n)!=errNone)
  126. {
  127. void *q = NULL;
  128. do
  129. {
  130. if ((size_t)AvailMemory()>MIN_DYNAMIC_LIMIT+n)
  131. q = MemGluePtrNew(n);
  132. } while (!q && NodeHibernate());
  133. if (q) 
  134. {
  135. memcpy(q,p,MemPtrSize(p));
  136. MemPtrFree(p);
  137. }
  138. else
  139. ShowOutOfMemory();
  140. p = q;
  141.     }
  142. #ifdef TRACKMEMORY
  143. DebugMessage("%08x realloc:%d %d %d",p,n,q,q-AvailMemory());
  144. if (n>1024)
  145. ThreadSleep(300);
  146. #endif
  147. return p;
  148. }
  149. void* CodeAlloc(int Size) { return malloc(Size); }
  150. void CodeFree(void* Code,int Size) { free(Code); }
  151. void CodeLock(void* Code,int Size) {}
  152. void CodeUnlock(void* Code,int Size) 
  153. {
  154. // instruction cache flush needed
  155. #ifdef ARM
  156. if (FlushCache.Ptr)
  157. ((void(*)())FlushCache.Ptr)();
  158. #endif
  159. }
  160. void WriteBlock(block* Block,int Ofs,const void* Src,int Length)
  161. {
  162. if (IsHeapStorage(Block))
  163. DmWrite((void*)Block->Ptr,Ofs,Src,Length);
  164. else
  165. memcpy((char*)Block->Ptr+Ofs,Src,Length);
  166. }
  167. void FreeBlock(block* Block)
  168. {
  169. if (Block)
  170. {
  171. context* p = Context();
  172. if (IsHeapStorage(Block))
  173. {
  174. int FtrId = Block->Id;
  175. if (p->FtrId > FtrId)
  176. p->FtrId = FtrId;
  177. FtrPtrFree(p->ProgramId,(UInt16)FtrId);
  178. }
  179. else
  180. free((char*)Block->Ptr);
  181. Block->Id = 0;
  182. Block->Ptr = NULL;
  183. }
  184. }
  185. bool_t SetHeapBlock(int n,block* Block,int Heap)
  186. {
  187. block New;
  188. if (!Block->Id && (Heap & HEAP_DYNAMIC))
  189. return 0;
  190. if (IsHeapStorage(Block) && (Heap & HEAP_STORAGE))
  191. return 0;
  192. if (!AllocBlock(n,&New,1,Heap))
  193. return 0;
  194. WriteBlock(&New,0,Block->Ptr,n);
  195. FreeBlock(Block);
  196. *Block = New;
  197. return 1;
  198. }
  199. #ifdef ARM
  200. static NOINLINE void FlushData(volatile const void* ptr)
  201. {
  202. const int zero = 0;
  203. asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (ptr));  // clean+invalidate D entry
  204. asm volatile ("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero)); // drain write buffer
  205. }
  206. static NOINLINE void FlushTLB()
  207. {
  208. const int zero = 0;
  209. asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero)); // invalidate I and D TLB
  210. }
  211. #endif
  212. static NOINLINE int GetFtrId(context* p)
  213. {
  214. UInt32 v;
  215. int FtrId = max(p->FtrId,FTRID_MIN);
  216. for (;FtrId<FTRID_MAX;++FtrId)
  217. if (FtrGet(p->ProgramId,(UInt16)FtrId,&v)==ftrErrNoSuchFeature)
  218. return FtrId;
  219. return -1;
  220. }
  221. bool_t AllocBlock(size_t n,block* Block,bool_t Optional,int Heap)
  222. {
  223. context* p = Context();
  224. uint32_t Storage,Max;
  225. void* Ptr = NULL;
  226. if (!n)
  227. {
  228. Block->Id = 0;
  229. Block->Ptr = NULL;
  230. return 1;
  231. }
  232. if (Heap == HEAP_ANY && !p->TryDynamic)
  233. Heap = HEAP_STORAGE;
  234. if ((Heap & HEAP_STORAGEWR) && (n<16384 || !QueryAdvanced(ADVANCED_MEMORYOVERRIDE)))
  235. Heap &= ~HEAP_STORAGEWR;
  236. if (Optional)
  237. {
  238. if ((Heap & (HEAP_STORAGE|HEAP_STORAGEWR)) && MemHeapFreeBytes(StorageId,&Storage,&Max)==errNone && (int)Storage<128*1024+n)
  239. Heap &= ~(HEAP_STORAGE|HEAP_STORAGEWR);
  240. if ((Heap & HEAP_DYNAMIC) && AvailMemory()<((Heap & HEAP_STORAGE)?2048:512)*1024+n)
  241. Heap &= ~HEAP_DYNAMIC;
  242. }
  243. if (Heap & HEAP_STORAGEWR)
  244. {
  245. int FtrId = GetFtrId(p);
  246. if (FtrId>=0)
  247. {
  248. do
  249. {
  250. if (FtrPtrNew(p->ProgramId,(UInt16)FtrId,n,&Ptr)==errNone)
  251. break;
  252. } while (NodeHibernate());
  253. if (Ptr)
  254. {
  255. uint32_t Phy = MemVirtToPhy(Ptr);
  256. void* PtrWr = MemAsWritable(Phy);
  257. if (!PtrWr || memcmp(Ptr,PtrWr,n)!=0)
  258. {
  259. //ShowMessage("","Memory tweak failed for address virt:%08x phy:%08x tmp:%08xnPlease report to developer!",Ptr,Phy,PtrWr);
  260. PtrWr = NULL;
  261. }
  262. if (PtrWr)
  263. {
  264. p->FtrId = FtrId+1;
  265. Block->Id = FtrId;
  266. Block->Ptr = PtrWr;
  267. return 1;
  268. }
  269. FtrPtrFree(p->ProgramId,(UInt16)FtrId);
  270. Ptr = NULL;
  271. }
  272. }
  273. }
  274. if (Heap & HEAP_DYNAMIC)
  275. {
  276. Ptr = malloc(n);
  277. if (Ptr)
  278. {
  279. Block->Ptr = Ptr;
  280. Block->Id = 0;
  281. return 1;
  282. }
  283. }
  284. if (Heap & HEAP_STORAGE)
  285. {
  286. int FtrId = GetFtrId(p);
  287. if (FtrId>=0)
  288. {
  289. do
  290. {
  291. if (MemHeapFreeBytes(StorageId,&Storage,&Max)==errNone && (int)Max<n+8192)
  292. continue;
  293. if (FtrPtrNew(p->ProgramId,(UInt16)FtrId,n,&Ptr)==errNone)
  294. break;
  295. } while (!Optional && NodeHibernate());
  296. if (Ptr)
  297. {
  298. p->FtrId = FtrId+1;
  299. Block->Id = FtrId;
  300. Block->Ptr = Ptr;
  301. return 1;
  302. }
  303. }
  304. }
  305. if (!Optional)
  306. ShowOutOfMemory();
  307. return 0;
  308. }
  309. void* PhyMemAlloc(int Length,phymemblock* Blocks,int* BlockCount) { return NULL; }
  310. void PhyMemFree(void* p,phymemblock* Blocks,int BlockCount) {}
  311. void* PhyMemBeginEx(phymemblock* Blocks,int BlockCount,bool_t Cached) { return NULL; }
  312. void* PhyMemBegin(uint32_t Phy,uint32_t Length,bool_t Cached) { return NULL; }
  313. void PhyMemEnd(void* Virt) {}
  314. void CheckHeap() 
  315. {
  316. assert(MemHeapCheck(MemHeapID(0,0))==0);
  317. }
  318.  
  319. size_t AvailMemory()
  320. {
  321. uint32_t Max = 0;
  322. uint32_t Free = 0;
  323. MemHeapFreeBytes(MemHeapID(0,0),&Free,&Max);
  324. return Free;
  325. }
  326. void CodeFindPages(void* Ptr,uint8_t** PMin,uint8_t** PMax,size_t* PPageSize)
  327. {
  328. if (PMin)
  329. *PMin = (uint8_t*)Ptr;
  330. if (PMax)
  331. *PMax = (uint8_t*)Ptr;
  332. if (PPageSize)
  333. *PPageSize = 4096;
  334. }
  335. bool_t MemGetInfo(memoryinfo* Info)
  336. {
  337. #ifdef ARM
  338. int Model = QueryPlatform(PLATFORM_MODEL);
  339. if (Model == MODEL_TUNGSTEN_T || Model == MODEL_TUNGSTEN_T2)
  340. {
  341. if (Info)
  342. {
  343. memset(Info,0,sizeof(memoryinfo));
  344. Info->TLB = (uint32_t*)0x20010000;
  345. Info->MemBase[0] = 0x10100000;
  346. Info->MemSize[0] = 14;
  347. Info->UnusedArea[0] = 0xB0200000;
  348. Info->MemBase[1] = 0x11000000;
  349. Info->MemSize[1] = 16;
  350. Info->UnusedArea[1] = 0xB1000000;
  351. }
  352. return 1;
  353. }
  354. #endif
  355. return 0;
  356. }
  357. void* MemAsWritable(uint32_t Phy)
  358. {
  359. #ifdef ARM
  360. memoryinfo Info;
  361. uint32_t v;
  362. bool_t Changed;
  363. int n,i,j;
  364. if (!Phy)
  365. return NULL;
  366. if (!MemGetInfo(&Info))
  367. return NULL;
  368. for (n=0;n<2;++n)
  369. if (Phy >= Info.MemBase[n] && Phy < Info.MemBase[n]+(Info.MemSize[n]<<20))
  370. {
  371. Phy = Phy - Info.MemBase[n] + Info.UnusedArea[n];
  372. Changed = 0;
  373. for (n=0;n<2;++n)
  374. {
  375. j = Info.UnusedArea[n]>>20;
  376. v = Info.MemBase[n] | 0xC4E;
  377. for (i=0;i<Info.MemSize[n];i++,v+=1024*1024,++j)
  378. if (Info.TLB[j] != v)
  379. {
  380. Info.TLB[j] = v;
  381. FlushData(Info.TLB+j);
  382. Changed = 1;
  383. }
  384. }
  385. if (Changed)
  386. FlushTLB();
  387. return (void*)Phy;
  388. }
  389. #endif
  390. return NULL;
  391. }
  392. void* MemPhyToVirt(uint32_t Phy)
  393. {
  394. #ifdef ARM
  395. int Model = QueryPlatform(PLATFORM_MODEL);
  396. switch (Model)
  397. {
  398. case MODEL_TUNGSTEN_T3:
  399. case MODEL_TUNGSTEN_T5:
  400. case MODEL_ZIRE_72:
  401. case MODEL_LIFEDRIVE:
  402. case MODEL_PALM_TX:
  403. case MODEL_TREO_650:
  404. if (Phy >= 0x44000000 && Phy < 0x44100000) // XScale LCD
  405. return (void*)(Phy+0x94000000-0x44000000);
  406. break;
  407. case MODEL_TUNGSTEN_C:
  408. case MODEL_TUNGSTEN_E2:
  409. if (Phy >= 0x44000000 && Phy < 0x44100000) // XScale LCD
  410. return (void*)(Phy+0x92000000-0x44000000);
  411. break;
  412. //case MODEL_TUNGSTEN_T: //(borderless mode not supported)
  413. case MODEL_ZIRE_71:
  414. case MODEL_TUNGSTEN_E:
  415. case MODEL_TUNGSTEN_T2:
  416. if (Phy >= 0xFFF00000) // OMAP
  417. return (void*)Phy;
  418. break;
  419. }
  420. #endif
  421. return NULL;
  422. }
  423. uint32_t MemVirtToPhy(void* p)
  424. {
  425. #ifdef ARM
  426. int n;
  427. memoryinfo Info;
  428. uint32_t Ptr = (uint32_t)p;
  429. int Model = QueryPlatform(PLATFORM_MODEL);
  430. switch (Model)
  431. {
  432. case MODEL_ZIRE_72:
  433. case MODEL_TUNGSTEN_C:
  434. case MODEL_TUNGSTEN_E2:
  435. case MODEL_TUNGSTEN_T3:
  436. if (Ptr >= 0x00000000 && Ptr < 0x04000000) //total memory
  437. return Ptr+0xA0000000;
  438. break;
  439. case MODEL_TUNGSTEN_T5:
  440. if (Ptr >= 0x00200000 && Ptr < 0x00600000) //dynamic
  441. return Ptr+0xA1C00000-0x00200000;
  442. // no info about storage yet...
  443. break;
  444. case MODEL_TREO_650:
  445. if (Ptr >= 0x64000000 && Ptr < 0x64500000) //dynamic
  446. return Ptr+0xA1A00000-0x64000000;
  447. if (Ptr >= 0x73100000 && Ptr < 0x73c00000) //storage
  448. return Ptr+0xA0F00000-0x73100000;
  449. break;
  450. case MODEL_LIFEDRIVE:
  451. if (Ptr >= 0x00200000 && Ptr < 0x00800000) //dynamic
  452. return Ptr+0xA1A00000-0x00200000;
  453. if (Ptr >= 0x00800000 && Ptr < 0x01430000) //storage
  454. return Ptr+0xA0DD0000-0x00800000;
  455. break;
  456. case MODEL_PALM_TX:
  457. if (Ptr >= 0x00200000 && Ptr < 0x00800000) //dynamic
  458. return Ptr+0xA1A00000-0x00200000;
  459. if (Ptr >= 0x00800000 && Ptr < 0x013D0000) //storage
  460. return Ptr+0xA0E30000-0x00800000;
  461. break;
  462. case MODEL_ZIRE_71:
  463. if (Ptr >= 0x00100000 && Ptr < 0x00200000) //dynamic
  464. return Ptr+0x10010000-0x00100000;
  465. if (Ptr >= 0x00200000 && Ptr < 0x00fe0000) //storage
  466. return Ptr+0x10120000-0x00200000;
  467. break;
  468. case MODEL_TUNGSTEN_E:
  469. if (Ptr >= 0x00100000 && Ptr < 0x00300000) //dynamic
  470. return Ptr+0x10020000-0x00100000;
  471. if (Ptr >= 0x00300000 && Ptr < 0x01fd0000) //storage
  472. return Ptr+0x10230000-0x00300000;
  473. break;
  474. case MODEL_TUNGSTEN_T:
  475. case MODEL_TUNGSTEN_T2:
  476. if (Ptr >= 0x00100000 && Ptr < 0x001c9000) //dynamic
  477. return Ptr+0x10037000-0x00100000;
  478. if (Ptr >= 0x00200000 && Ptr < 0x01000000) //storage
  479. return Ptr+0x10100000-0x00200000;
  480. if (Ptr >= 0x01000000 && Ptr < 0x02000000) //T2 additional storage
  481. return Ptr+0x11000000-0x01000000;
  482. break;
  483. }
  484. if (MemGetInfo(&Info))
  485. for (n=0;n<2;++n)
  486. if (Ptr >= Info.UnusedArea[n] && Ptr < Info.UnusedArea[n]+(Info.MemSize[n]<<20))
  487. return Ptr-Info.UnusedArea[n]+Info.MemBase[n];
  488. #endif
  489. return 0;
  490. }
  491. void Mem_Init()
  492. {
  493. Context()->TryDynamic = Context()->StartUpMemory > TRY_DYNAMIC;
  494. StorageId = MemHeapID(0,1);
  495. #ifdef HAVE_PALMONE_SDK
  496. {
  497. UInt32 Version;
  498. if (FtrGet(sysFtrCreator,sysFtrNumDmAutoBackup,&Version)==errNone && Version==1)
  499. StorageId = 1|dbCacheFlag;
  500. }
  501. #endif
  502. #ifdef ARM
  503. if (AllocBlock(MAX_CACHE+sizeof(uint32_t),&FlushCache,0,HEAP_ANY))
  504. {
  505. uint32_t p[64];
  506. int i;
  507. for (i=0;i<64;++i)
  508. p[i] = 0xE51F0008; //ldr r0,[pc,#-8]
  509. for (i=0;i<=MAX_CACHE-sizeof(p);i+=sizeof(p))
  510. WriteBlock(&FlushCache,i,p,sizeof(p));
  511. p[0] = 0xE1A0F00E; // mov pc,lr
  512. WriteBlock(&FlushCache,i,p,sizeof(uint32_t));
  513. }
  514. #endif
  515. }
  516. void Mem_Done()
  517. {
  518. #ifdef ARM
  519. FreeBlock(&FlushCache);
  520. #endif
  521. }
  522. #endif