00001
00021 #include "pm.h"
00022 #include <signal.h>
00023 #include "mproc.h"
00024 #include "param.h"
00025
00026 #define DATA_CHANGED 1
00027 #define STACK_CHANGED 2
00028
00029
00030
00031
00032 PUBLIC int do_brk()
00033 {
00034
00035
00036
00037
00038
00039
00040
00041
00042 register struct mproc *rmp;
00043 int r;
00044 vir_bytes v, new_sp;
00045 vir_clicks new_clicks;
00046
00047 rmp = mp;
00048 v = (vir_bytes) m_in.addr;
00049 new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
00050 if (new_clicks < rmp->mp_seg[D].mem_vir) {
00051 rmp->mp_reply.reply_ptr = (char *) -1;
00052 return(ENOMEM);
00053 }
00054 new_clicks -= rmp->mp_seg[D].mem_vir;
00055 if ((r=get_stack_ptr(who_e, &new_sp)) != OK)
00056 panic(__FILE__,"couldn't get stack pointer", r);
00057 r = adjust(rmp, new_clicks, new_sp);
00058 rmp->mp_reply.reply_ptr = (r == OK ? m_in.addr : (char *) -1);
00059 return(r);
00060 }
00061
00062
00063
00064
00065 PUBLIC int adjust(rmp, data_clicks, sp)
00066 register struct mproc *rmp;
00067 vir_clicks data_clicks;
00068 vir_bytes sp;
00069 {
00070
00071
00072
00073
00074
00075
00076 register struct mem_map *mem_sp, *mem_dp;
00077 vir_clicks sp_click, gap_base, lower, old_clicks;
00078 int changed, r, ft;
00079 long base_of_stack, delta;
00080
00081 mem_dp = &rmp->mp_seg[D];
00082 mem_sp = &rmp->mp_seg[S];
00083 changed = 0;
00084
00085 if (mem_sp->mem_len == 0) return(OK);
00086
00087
00088 base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
00089 sp_click = sp >> CLICK_SHIFT;
00090 if (sp_click >= base_of_stack) return(ENOMEM);
00091
00092
00093 delta = (long) mem_sp->mem_vir - (long) sp_click;
00094 lower = (delta > 0 ? sp_click : mem_sp->mem_vir);
00095
00096
00097 #define SAFETY_BYTES (384 * sizeof(char *))
00098 #define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
00099 gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
00100 if (lower < gap_base) return(ENOMEM);
00101
00102
00103 old_clicks = mem_dp->mem_len;
00104 if (data_clicks != mem_dp->mem_len) {
00105 mem_dp->mem_len = data_clicks;
00106 changed |= DATA_CHANGED;
00107 }
00108
00109
00110 if (delta > 0) {
00111 mem_sp->mem_vir -= delta;
00112 mem_sp->mem_phys -= delta;
00113 mem_sp->mem_len += delta;
00114 changed |= STACK_CHANGED;
00115 }
00116
00117
00118 ft = (rmp->mp_flags & SEPARATE);
00119 #if (CHIP == INTEL && _WORD_SIZE == 2)
00120 r = size_ok(ft, rmp->mp_seg[T].mem_len, rmp->mp_seg[D].mem_len,
00121 rmp->mp_seg[S].mem_len, rmp->mp_seg[D].mem_vir, rmp->mp_seg[S].mem_vir);
00122 #else
00123 r = (rmp->mp_seg[D].mem_vir + rmp->mp_seg[D].mem_len >
00124 rmp->mp_seg[S].mem_vir) ? ENOMEM : OK;
00125 #endif
00126 if (r == OK) {
00127 int r2;
00128 if (changed && (r2=sys_newmap(rmp->mp_endpoint, rmp->mp_seg)) != OK)
00129 panic(__FILE__,"couldn't sys_newmap in adjust", r2);
00130 return(OK);
00131 }
00132
00133
00134 if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks;
00135 if (changed & STACK_CHANGED) {
00136 mem_sp->mem_vir += delta;
00137 mem_sp->mem_phys += delta;
00138 mem_sp->mem_len -= delta;
00139 }
00140 return(ENOMEM);
00141 }
00142
00143 #if (CHIP == INTEL && _WORD_SIZE == 2)
00144
00145
00146
00147 PUBLIC int size_ok(file_type, tc, dc, sc, dvir, s_vir)
00148 int file_type;
00149 vir_clicks tc;
00150 vir_clicks dc;
00151 vir_clicks sc;
00152 vir_clicks dvir;
00153 vir_clicks s_vir;
00154 {
00155
00156
00157
00158
00159
00160
00161
00162
00163 int pt, pd, ps;
00164
00165 pt = ( (tc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
00166 pd = ( (dc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
00167 ps = ( (sc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
00168
00169 if (file_type == SEPARATE) {
00170 if (pt > MAX_PAGES || pd + ps > MAX_PAGES) return(ENOMEM);
00171 } else {
00172 if (pt + pd + ps > MAX_PAGES) return(ENOMEM);
00173 }
00174
00175 if (dvir + dc > s_vir) return(ENOMEM);
00176
00177 return(OK);
00178 }
00179 #endif
00180