;***************************************************** ;* ;* MEM Entry Points ;* ;* Each process descriptor points to a linked ;* list of MDs that describe memory segments that ;* it owns. The MDs note the starting paragraph ;* and a MAU that the Memory Segment is in. ;* ;* Format of MDs on p_mem lists: ;* ;* +----+----+----+----+----+----+----+----+----+----+ ;* | link | start | length | flags | mau | ;* +----+----+----+----+----+----+----+----+----+----+ ;* ;* link link field for p_mem list ;* start starting paragraph of memory segment ;* length length in paragraphs of memory segment ;* flags load,code,and share as in MPB ;* mau offset of MAU in SYSDAT that segment is ;* allocated from ;* ;***************************************************** ;============ malloc_entry: ;============ ; Allocate Memory - memory is allocated from MAUs. ; First we try to allocate memory from MAUs that has ; memory segments already allocated by this process. ; If that fails, we try to create a new MAU from the ; Memory Free List (MFL). If both fails, an error is ; is returned to the user. ; ; input: DX = MPB in u_wrkseg ; output: BX = 0 if successful (unused memory) ; = 1 if successful (shared code) ; = 0ffffh if failure ; CX = error code ; ; Format of MPB: ; ; +----+----+----+----+----+----+----+----+----+----+ ; | start | min | max | pdadr | flags | ; +----+----+----+----+----+----+----+----+----+----+ ; ; start - if non-zero, an absolute request ; min - minimum length that will satisfy the request ; max - maximum length wanted ; We will try to allocate the maximum ; but will be satisfied with as little as the ; minimum. ; pdadr - Process Descriptor to allocate memory to. ; Note - PD can not be a current process unless ; it is the calling process. ; The Calling process must explicitly release ; the memory if the PD never becomes a process. ; Otherwise, memory is released upon termination. ; If pdadr is 0, then calling process allocates ; the memory. ; flags - 00001h Load This segment initialized from ; a disk file ; 00002h Shared This is a sharable segment ; 00004h Code This is a Code segment ; Get a MD for use in the p_mem list ; DX -> MPB (u_wrkseg) push dx ! call getmd ! pop dx ; BX -> MD jcxz mall_gmd mov bx,0ffffh ! ret mall_gmd: ; fill PDADR field in case its zero push es ! mov es,u_wrkseg ;save UDA mov di,dx ! mov ax,es:mpb_pdadr[di] cmp ax,0 ! jne mall_gpd mov ax,rlr mov es:mpb_pdadr[di],ax mall_gpd: pop es ;ES=UDA cmp ax,rlr ! je mall_pdv1 push ax ! push bx push dx ! push di mov bx,offset thrd_spb ;ok to call sync on mov cx,f_sync ;thread after sync-ing call osif ;on memory pop di ! pop dx pop bx ! pop ax mov si,(offset thrdrt)-p_thread mall_pdnxt: mov si,p_thread[si] cmp si,0 ! je mall_pdver cmp si,ax ! jne mall_pdnxt cmp si,rlr ! je mall_pdver mov cx,e_active_pd push bx ; save MD addr mov bx,offset thrd_spb mov cx,f_unsync call osif pop bx ; restore MD addr jmp mall_err mall_pdver: push ax ! push bx push dx ! push di mov bx,offset thrd_spb mov cx,f_unsync call osif pop di ! pop dx pop bx ! pop ax ; verify MIN <= MAX mall_pdv1: push es ! mov es,u_wrkseg mov cx,es:mpb_min[di] cmp cx,es:mpb_max[di] jbe mpb_ok mov es:mpb_max[di],cx mpb_ok: ; Make sure total allocation <= MMP mov si,ax ! add si,(p_mem - ms_link) sub cx,cx ! push si max_chk_nxt: mov si,ms_link[si] cmp si,0 ! je max_chk_done add cx,ms_length[si] jmps max_chk_nxt max_chk_done: pop si ! mov ax,mmp sub ax,cx cmp ax,0 ! jne not_zero no_min: pop es mall_nomem: mov cx,e_no_memory mall_err: call freemd ; Free the Memory Descriptor mov bx,0ffffh ! ret ; CX=Error Code set previously not_zero: cmp ax,es:mpb_min[di] ! jb no_min cmp ax,es:mpb_max[di] ! jae max_ok mov es:mpb_max[di],ax max_ok: ; initialize local variables push di ! mov di,offset beststart mov cx,11 ! sub ax,ax mov es,sysdat rep stosw ! pop di sub cx,cx pop es ; try to allocate memory mall_next: mov si,ms_link[si] cmp si,0 ! je mall_ml cmp cx,ms_mau[si] ! je mall_next ; here's a MAU we haven't tried... ; CX=last MAU tried ; DX=MPB adr in u_wrkseg ; BX=New MD ; SI=current MD push cx ! push dx ! push bx ! push si mov bx,ms_mau[si] call mall_try_mau pop si ! pop bx ! pop dx ; Plus DI=MAU address cmp cx,0 ! pop cx ! jne mall_next ; exact allocation ; succesful allocation jmp mall_linkit mall_ml: ; We must create a new MAU from MFL push bx ! push dx mov ds,u_wrkseg mov bx,offset mfl ! mov cx,f_mlalloc call osif mov ds,sysdat ;BX=MAU, (New MD,MPB on stack) jcxz mall_ml0 pop dx ! pop bx jmp mall_linkit mall_ml0: ; We have a new MAU ;place MAU on MAL mov si,mal mov m_link[bx],si mov mal,bx ;allocate memory pop dx ! push dx sub si,si call mall_try_mau pop dx ! pop bx ;DI=MAU, BX=New MD, DX=MPB in u_wrkseg mall_linkit: ;BX -> MD ;DX -> MPB in u_wrkseg cmp beststart,0 ! jne yesmem ;if ccpm ; jmp mall_nomem ;endif ;if mpm ; We couldn't find any memory ... ; lets take something off the SCL pushf ! cli mov di,scl cmp di,0 ! jne take_one_off ; No where else to try, giveup. popf ! jmp mall_nomem ; take first SHARE PD off SCL take_one_off: mov ax,p_thread[di] mov scl,ax popf ; Free its memory ; We can assume only one memory segment push bx ! push dx mov bx,p_mem[di] push di ! push ds push di ! push ms_start[bx] push ss ! pop ds mov dx,sp ! mov cx,f_memfree call osif pop ax ! pop ax pop ds ! pop di ; There should be no error. ; Put SHARE PD on PUL pushf ! cli mov ax,pul mov p_link[di],ax mov pul,di popf ; Let's assume we just released a partition ; and try the ML Alloc again. pop dx ! pop bx jmp mall_ml ;endif ; We have memory ... yesmem: push es ! mov es,u_wrkseg mov di,dx mov ax,beststart mov es:mpb_start[di],ax mov ms_start[bx],ax mov ax,bestlen mov es:mpb_min[di],ax mov es:mpb_max[di],ax mov ms_length[bx],ax mov ax,es:mpb_flags[di] mov ms_flags[bx],ax mov si,bestsi cmp si,0 ! jne mall_l0 mov si,es:mpb_pdadr[di] add si,(p_mem-ms_link) mall_l0:mov ax,ms_link[si] ! mov ms_link[bx],ax mov ms_link[si],bx mov di,bestmau mov ms_mau[bx],di pop es ! sub cx,cx ! mov bx,cx ! ret mall_try_mau: ;------------ ; input: BX -> MAU ; DX -> MPB in u_wrkseg ; SI = MS Root that MAU came from ; output: CX = 0, found exact allocation ; else, exact not found ; save root,mau mov currsi,si mov currmau,bx ; copy user's MPB into local MPB push dx ! push ds ! push es mov ds,u_wrkseg mov es,sysdat mov si,dx ! mov di,offset currmpb mov cx,5 ! rep movsw pop es ! pop ds mov dx,offset currmpb mov cx,f_maualloc ! call osif pop di jcxz chkbest ret chkbest: push es ! mov es,u_wrkseg mov si,offset currmpb mov ax,mpb_max[si] sub cx,cx cmp ax,es:mpb_max[di] pop es jz replacebest mov cx,3 ! mov bx,currmau mov di,si cmp ax,bestlen ! jbe freeworst replacebest: mov di,offset beststart mov bx,bestmau call freeworst mov si,offset currmpb mov ax,mpb_start[si] ! mov beststart,ax mov ax,mpb_max[si] ! mov bestlen,ax mov ax,currmau ! mov bestmau,ax mov ax,currsi ! mov bestsi,ax savret: ret freeworst: ; DI->Start, CX=Return Code, BX=MAU cmp word ptr [di],0 ! je savret ; free worst memory push cx ! push ds push word ptr [di] ! push word ptr [di] push bx ! push ss ! pop ds mov dx,sp ! mov cx,f_maufree call osif ; if MAU empty, free MAU cmp cx,0 ! jne mflret cmp bx,0ffffh ! jne mflret pop bx ! pop ax ! pop ax ! pop ds ; take off MAL ; BX = MAU address mov ax,bx ! mov bx,(offset mal)-m_link mfl1: mov si,bx ! mov bx,m_link[si] cmp bx,ax ! jne mfl1 push ax mov ax,m_link[bx] ! mov m_link[si],ax pop bx ; Replace into MFL mov cx,f_mlfree mov dx,bx ! mov bx,offset mfl call osif ! pop cx ! ret mflret: pop bx ! pop ax ! pop ax pop ds ! pop cx ! ret ;=========== mfree_entry: ; 130 - Memory Free ;=========== ; Free the memory segment with the given segment addr. ; input: DX = MFPB in u_wrkseg ; output: BX = 0 if successful ; = 0ffffh on failure ; CX = error code ; ; Memory Free Parameter Block (MFPB) ; ; +----+----+----+----+ ; | start | pdadr | ; +----+----+----+----+ ; ; start - starting paragraph of area to be freed. ; pdadr - PD to free memory from. If 0, then calling ; process. If non-zero, the PD must not be ; a current process. push es ! mov es,u_wrkseg mov si,dx mov bx,es:mfpb_pd[si] mov dx,es:mfpb_start[si] pop es ; BX = pdadr ; DX = start paragraph cmp bx,0 ! jne mfree_chkpd mov bx,rlr jmps mfree_g1 mfree_chkpd: push bx ! push dx mov bx,offset thrd_spb mov cx,f_sync call osif pop dx ! pop bx mov si,(offset thrdrt)-p_thread mfree_nxtpd: mov si,p_thread[si] cmp si,0 ! je mfree_gotpd cmp si,bx ! jne mfree_nxtpd cmp si,rlr ! je mfree_gotpd mov bx,offset thrd_spb mov cx,f_unsync call osif mov bx,0ffffh mov cx,e_active_pd ret mfree_gotpd: push bx ! push dx mov bx,offset thrd_spb mov cx,f_unsync call osif pop dx ! pop bx mfree_g1: lea si,p_mem[bx] mfree_next: mov bx,si ! mov si,ms_link[bx] cmp si,0 ! je mfree_err cmp ms_start[si],dx ! je mfree_it ja mfree_next mov ax,ms_start[si] add ax,ms_length[si] cmp ax,dx ! jbe mfree_next push dx ! push si call mfree_it pop si ! pop dx cmp cx,0 ! jne mfree_next mfree_exit: sub bx,bx ! mov cx,bx ! ret mfree_err: mov bx,0ffffh ! mov cx,e_no_memory ret mfree_it: ;-------- ; input: BX = root ; SI = MD ([bx]) ; DX = segment to free ; output: BX = 0,0ffffh (success,failure) ; CX = Error Code push bx ! push si ! push dx ;push MAF structure push dx ! push ms_start[si] push ms_mau[si] mov dx,sp ! push ss ! pop ds mov cx,f_maufree ! call osif mov bp,bx ;if bp=0,MAU not empty mov ds,sysdat ;pop MAF structure pop ax ! pop ax ! pop ax pop dx ! pop si ! pop bx ;DX=segment to free ;BX=root ;SI=MD ( [BX] ) cmp cx,0 jne mfree_err cmp dx,ms_start[si] ! je mfree_off ;decrease length sub dx,ms_start[si] mov ms_length[si],dx mfree_r: jmps mfree_exit ;take off p_mem list mfree_off: mov ax,ms_link[si] ! mov ms_link[bx],ax ;free MD push ms_mau[si] ! push bp mov bx,si ! call freemd pop bp ! pop dx ;free MAU if empty cmp bp,0 ! je mfree_exit ;find it on MAL mov di,(offset mal)-m_link mfree_nmal: mov si,di ! mov di,m_link[si] cmp di,dx ! jne mfree_nmal ;release from MAL mov ax,m_link[di] ! mov m_link[si],ax mov m_link[di],0 ;release to MFL mov bx,offset mfl ! mov cx,f_mlfree jmp osif