static void ualarm_AST(Alarm *a) { int iss; unsigned long now[2]; iss = sys$gettim(now); if (VMSERR(iss)) lib$signal(iss); if (a->function == UAL_SET || a->function == UAL_CLEAR) { if (a0->function == UAL_ACTIVE) { iss = sys$cantim(a0,PSL$C_USER); if (VMSERR(iss)) lib$signal(iss); iss = lib$subx(a0->remain, now, a->remain); if (VMSERR(iss)) lib$signal(iss); if (a->remain[1] & 0x80000000) a->remain[0] = a->remain[1] = 0; } if (a->function == UAL_SET) { a->function = a0->function; a0->function = UAL_ACTIVE; a0->repeat = a->repeat; if (a0->repeat) { a0->interval[0] = a->interval[0]; a0->interval[1] = a->interval[1]; } a0->delay[0] = a->delay[0]; a0->delay[1] = a->delay[1]; iss = lib$subx(now, a0->delay, a0->remain); if (VMSERR(iss)) lib$signal(iss); iss = sys$setimr(0,a0->delay,ualarm_AST,a0); if (VMSERR(iss)) lib$signal(iss); } else { a->function = a0->function; a0->function = UAL_NULL; } iss = sys$setef(alarm_ef); if (VMSERR(iss)) lib$signal(iss); } else if (a->function == UAL_ACTIVE) { if (a->repeat) { iss = lib$subx(now, a->interval, a->remain); if (VMSERR(iss)) lib$signal(iss); iss = sys$setimr(0,a->interval,ualarm_AST,a); if (VMSERR(iss)) lib$signal(iss); } else { a->function = UAL_NULL; } iss = sys$wake(0,0); if (VMSERR(iss)) lib$signal(iss); lib$signal(SS$_ASTFLT); } else { lib$signal(SS$_BADPARAM); } }
/* * --------------------------------------------- * System call to cancel timer. * --------------------------------------------- */ void cancel_timer(TID tid) { /* An interrupt should never cancel a timer that has been started in the mainline code. * Or else it is possible the mainline code might hibernate for ever. * In VMS, interrupt is equivalent to being in an AST. Hence assert we are never in an AST if we are here. * The only exception is if we are exiting in which case we are not going to be hibernating so it is ok. */ assert(!lib$ast_in_prog() || process_exiting); sys$cantim(tid, 0); }
/*********************************************************************** This routine is called to wait for a clustered data base to transition to a new state. If the "state" parameter is non-zero, then it is considered a bit mask, with state zero being the lsb, etc. (All of these masks are symbolically defined in ccp.h as CCST_MASK_nnnnn.) In this case we will return when the state is obtained. If the state is zero, we will return when the ccp_cycle count is bumped, indicating that we have transitioned into read mode. In any event we will return after the "next" cycle has passed, so that if we "miss" our window, we can try again. ***********************************************************************/ bool ccp_userwait(gd_region *reg, uint4 state, int4 *timadr, unsigned short cycle) /* if timadr is non-zero, then the timeout quadword, else use the seg's timeout interval */ { int4 status; static void ccp_nocomm(); bool timer_on; sgmnt_data *seg; sgmnt_addrs *csa; int4 *timptr; char buff[(MM_BLOCK - 1) * DISK_BLOCK_SIZE]; short iosb[4]; error_def(ERR_CCPNOTFND); csa = &((vms_gds_info *)(reg->dyn.addr->file_cntl->file_info))->s_addrs; seg = ((vms_gds_info *)(reg->dyn.addr->file_cntl->file_info))->s_addrs.hdr; timptr = timadr ? timadr : (int4 *) &seg->ccp_response_interval; timer_on = timptr[0] != 0 && timptr[1] != 0; for (; ;) { ccp_communication_timeout = FALSE; if (timer_on) { status = sys$setimr(0, timptr, ccp_nocomm, ccp_nocomm, 0); if ((status & 1) == 0) rts_error(VARLSTCNT(1) status); } while (!CCP_SEGMENT_STATE(csa->nl, state) && csa->nl->ccp_cycle == cycle && !ccp_communication_timeout) { sys$hiber(); } if (ccp_communication_timeout && !(CCP_SEGMENT_STATE(csa->nl, state) || csa->nl->ccp_cycle != cycle)) { status = sys$qiow(EFN$C_ENF, ((vms_gds_info *)(reg->dyn.addr->file_cntl->file_info))->fab->fab$l_stv, IO$_READVBLK, &iosb[0], 0, 0, buff, SIZEOF(buff), 1, 0, 0, 0); if ((status & 1) && (iosb[0] & 1) && ((sgmnt_data *)buff)->freeze) continue; rts_error(VARLSTCNT(1) ERR_CCPNOTFND); }else break; } if (timer_on) sys$cantim(ccp_nocomm,0); return CCP_SEGMENT_STATE(csa->nl, state); }
void jnl_file_close(gd_region *reg, bool clean, bool dummy) { jnl_file_header header; sgmnt_addrs *csa; jnl_private_control *jpc; jnl_buffer_ptr_t jb; struct_jrec_eof eof_record; off_jnl_t eof_addr; uint4 status; error_def (ERR_PREMATEOF); error_def (ERR_JNLCLOSE); error_def (ERR_JNLWRERR); csa = &FILE_INFO(reg)->s_addrs; assert(csa->now_crit || (csa->hdr->clustered && (CCST_CLOSED == csa->nl->ccp_state))); ASSERT_JNLFILEID_NOT_NULL(csa) jpc = csa->jnl; #if defined(UNIX) if (csa->dbsync_timer) { cancel_timer((TID)csa); csa->dbsync_timer = FALSE; } #elif defined(VMS) /* See comment about ordering of the two statements below, in similar code in gds_rundown */ if (csa->dbsync_timer) { csa->dbsync_timer = FALSE; ++astq_dyn_avail; } sys$cantim(csa, PSL$C_USER); /* cancel all dbsync-timers for this region */ #endif if ((NULL == jpc) || (NOJNL == jpc->channel)) return; if (clean) { jb = jpc->jnl_buff; jnl_write_eof_rec(csa, &eof_record); jnl_flush(reg); assert(jb->dskaddr == jb->freeaddr); UNIX_ONLY(jnl_fsync(reg, jb->dskaddr);) UNIX_ONLY(assert(jb->freeaddr == jb->fsync_dskaddr);)
/* * ------------------------------------------------------ * Start hibernating by starting a timer using hiber_time * (in msecs) and doing a pause * ------------------------------------------------------ */ void hiber_start(uint4 hiber) { int4 hiber_time[2]; /* don't have static since can be interrupted by an AST */ int status_timr, status_wait, ast_in_prog; if (0 == hiber) return; /* in PRO code return */ hiber_time[0] = -time_low_ms((int4)hiber); hiber_time[1] = -time_high_ms((int4)hiber); if (hiber_time[1] == 0) hiber_time[1] -= 1; if (0 != (ast_in_prog = lib$ast_in_prog())) { /* sleep sounder but less permanently; * note that an AST may cause an inappropriate time to be used for another hiber_start in progress, * but that risk should be statistically small, and the consequences (as far as known) are not important */ status_timr = sys$setimr(efn_timer_ast, hiber_time, 0, hiber_start_ast, 0); assert(SS$_NORMAL == status_timr); if (SS$_NORMAL == status_timr) { status_wait = sys$waitfr(efn_timer_ast); assert(SS$_NORMAL == status_wait); } } else { /* timr->hiber should not be changed to timr->waitfr. The former waits for a wakeup or outofband event; whichever * happens sooner will stop the hiber while the latter does not recognize outofband events (like tp timeouts) */ status_timr = sys$setimr(efn_hiber_start, hiber_time, wake, hiber_start, 0); assert(SS$_NORMAL == status_timr); if (SS$_NORMAL == status_timr) { sys$hiber(); sys$cantim(hiber_start, 0); } } }
/* **++ ** ROUTINE: netlib_read ** ** FUNCTIONAL DESCRIPTION: ** ** tbs ** ** RETURNS: cond_value, longword (unsigned), write only, by value ** ** PROTOTYPE: ** ** tbs ** ** IMPLICIT INPUTS: None. ** ** IMPLICIT OUTPUTS: None. ** ** COMPLETION CODES: ** ** ** SIDE EFFECTS: None. ** **-- */ unsigned int netlib_read (struct CTX **xctx, struct dsc$descriptor *dsc, struct SINDEF *sa, unsigned int *sasize, unsigned int *salen, TIME *timeout, struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm) { struct CTX *ctx; struct IOR *ior; unsigned int status; ITMLST sname; int argc, do_from; VERIFY_CTX(xctx, ctx); SETARGCOUNT(argc); if (dsc->dsc$b_dtype != DSC$K_DTYPE_T && dsc->dsc$b_dtype != 0) return SS$_BADPARAM; if (dsc->dsc$b_class == DSC$K_CLASS_D) { if (dsc->dsc$w_length == 0) return SS$_BADPARAM; } else { if (dsc->dsc$b_class != DSC$K_CLASS_S && dsc->dsc$b_class != 0) return SS$_BADPARAM; } do_from = (argc > 3 && sa != 0 && sasize != 0 && *sasize != 0); if (argc > 7 && astadr != 0) { struct IOR *ior; GET_IOR(ior, ctx, iosb, astadr, (argc > 8) ? astprm : 0); if (do_from) ITMLST_INIT(sname, 0, sizeof(struct SINDEF), &ior->specior.from, &ior->specior.fromlen); if (do_from) { ior->spec_userfrom = sa; ior->spec_length = *sasize; ior->spec_retlen = salen; ior->iorflags = IOR_M_COPY_FROM; } else ior->iorflags = 0; if (timeout != 0) { ior->iorflags |= IOR_M_IO_TIMED; status = sys$setimr(netlib_asynch_efn, timeout, io_timeout, ior); if (!OK(status)) { FREE_IOR(ior); return status; } } status = sys$qio(netlib_asynch_efn, ctx->chan, IO$_READVBLK, &ior->iosb, io_completion, ior, dsc->dsc$a_pointer, dsc->dsc$w_length, do_from ? &sname : 0, 0, 0, 0); if (!OK(status)) { if (timeout != 0) sys$cantim(ior, 0); FREE_IOR(ior); } } else { struct NETLIBIOSBDEF myiosb; struct SINDEF from; unsigned short fromlen; int timed_out; if (do_from) ITMLST_INIT(sname, 0, sizeof(struct SINDEF), &from, &fromlen); timed_out = 0; if (argc > 5 && timeout != 0) { GET_IOR(ior, ctx, 0, 0, 0); ior->iorflags = IOR_M_IO_TIMED; status = sys$setimr(netlib_asynch_efn, timeout, io_timeout, ior); if (!OK(status)) { FREE_IOR(ior); return status; } } status = sys$qiow(netlib_synch_efn, ctx->chan, IO$_READVBLK, &myiosb, 0, 0, dsc->dsc$a_pointer, dsc->dsc$w_length, do_from ? &sname : 0, 0, 0, 0); if (argc > 5 && timeout != 0) { sys$cantim(ior, 0); timed_out = ior->iorflags & IOR_M_IO_TIMEOUT; FREE_IOR(ior); } if (OK(status)) { if (timed_out && myiosb.iosb_w_status == SS$_CANCEL) myiosb.iosb_w_status = SS$_TIMEOUT; status = netlib___cvt_status(&myiosb); } if (argc > 6 && iosb != 0) netlib___cvt_iosb(iosb, &myiosb); if (OK(status) && do_from) { unsigned int len; len = fromlen; if (len > *sasize) len = *sasize; memcpy(sa, &from, len); if (argc > 4 && salen != 0) *salen = len; } } return status; } /* netlib_read */
/* **++ ** ROUTINE: io_completion ** ** FUNCTIONAL DESCRIPTION: ** ** tbs ** ** RETURNS: cond_value, longword (unsigned), write only, by value ** ** PROTOTYPE: ** ** tbs ** ** IMPLICIT INPUTS: None. ** ** IMPLICIT OUTPUTS: None. ** ** COMPLETION CODES: ** ** ** SIDE EFFECTS: None. ** **-- */ static unsigned int io_completion (struct IOR *ior) { struct CTX *ctx = ior->ctx; ior->iorflags |= IOR_M_IO_COMPLETED; if (ior->iorflags & IOR_M_IO_TIMED) sys$cantim(ior, 0); if (ior->iosb.iosb_w_status == SS$_CANCEL && (ior->iorflags & IOR_M_IO_TIMEOUT)) ior->iosb.iosb_w_status = SS$_TIMEOUT; if (ior->iosbp != 0) netlib___cvt_iosb(ior->iosbp, &ior->iosb); if (ior->iorflags & IOR_M_COPY_LENGTH) { if (OK(ior->iosb.iosb_w_status) && ior->spec_retlen != 0) *(unsigned int *) ior->spec_retlen = ior->spec_length; ior->iorflags &= ~IOR_M_COPY_LENGTH; } if (ior->iorflags & IOR_M_COPY_FROM) { if (OK(ior->iosb.iosb_w_status) && ior->spec_userfrom != 0) { unsigned int len; len = ior->specior.fromlen; if (len > ior->spec_length) len = ior->spec_length; memcpy(ior->spec_userfrom, &ior->specior.from, len); if (ior->spec_retlen != 0) *(unsigned int *)ior->spec_retlen = len; } ior->iorflags &= ~IOR_M_COPY_FROM; } if (ior->iorflags & IOR_M_COPY_ADDRS) { struct HOSTENT *h; h = ior->spec_hostent; if (OK(ior->iosb.iosb_w_status)) { char *base; unsigned int *offlst; int i; base = (char *) h; i = 0; if (h->addrlist_offset != 0) { struct INADDRDEF *alist = ior->spec_useralist; offlst = (unsigned int *) (base+h->addrlist_offset); while (i < ior->spec_length && offlst[i] != 0) { alist[i] = *(struct INADDRDEF *) (base + offlst[i]); i++; } } if (ior->spec_retlen != 0) *(unsigned int *)ior->spec_retlen = i; } lib$free_vm(&hostent_size, &h); ior->iorflags &= ~IOR_M_COPY_ADDRS; } if (ior->iorflags & IOR_M_COPY_HOSTNAME) { struct HOSTENT *h; h = ior->spec_hostent; if (OK(ior->iosb.iosb_w_status)) { str$copy_r(ior->spec_usrdsc, &ior->specior.fromlen, h->buffer); if (ior->spec_retlen != 0) *(unsigned short *)ior->spec_retlen = ior->specior.fromlen; } lib$free_vm(&hostent_size, &h); ior->iorflags &= ~IOR_M_COPY_HOSTNAME; } if (ior->iorflags & IOR_M_NEW_CONTEXT) { if (OK(ior->iosb.iosb_w_status)) { *(struct CTX **) ior->spec_xnewctx = ior->spec_newctx; } else { sys$dassgn(((struct CTX *)ior->spec_newctx)->chan); netlib___free_ctx((struct CTX *) ior->spec_newctx); } ior->iorflags &= ~IOR_M_NEW_CONTEXT; } if (ior->astadr != 0) (*(ior->astadr))(ior->astprm); FREE_IOR(ior); return SS$_NORMAL; } /* io_completion */
/* * ------------------------------------------ * Hang the process for a specified time. * * Goes to sleep for a positive value. * Any caught signal will terminate the sleep * following the execution of that signal's catching routine. * * The actual hang duration should be NO LESS than the specified * duration for specified durations greater than .001 seconds. * Certain applications depend on this assumption. * * Arguments: * num - time to sleep * * Return: * none * ------------------------------------------ */ void op_hang(mval* num) { int ms; double tmp; mv_stent *mv_zintcmd; ABS_TIME cur_time, end_time; # ifdef VMS uint4 time[2]; int4 efn_mask, status; # endif DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; ms = 0; MV_FORCE_NUM(num); if (num->mvtype & MV_INT) { if (0 < num->m[1]) { assert(MV_BIAS >= 1000); /* if formats change overflow may need attention */ ms = num->m[1] * (1000 / MV_BIAS); } } else if (0 == num->sgn) /* if sign is not 0 it means num is negative */ { tmp = mval2double(num) * (double)1000; ms = ((double)MAXPOSINT4 >= tmp) ? (int)tmp : (int)MAXPOSINT4; } if (ms) { if (TREF(tpnotacidtime) * 1000 < ms) TPNOTACID_CHECK(HANGSTR); # if defined(DEBUG) && defined(UNIX) if (WBTEST_ENABLED(WBTEST_DEFERRED_TIMERS) && (3 > gtm_white_box_test_case_count) && (123000 == ms)) { DEFER_INTERRUPTS(INTRPT_NO_TIMER_EVENTS); DBGFPF((stderr, "OP_HANG: will sleep for 20 seconds\n")); LONG_SLEEP(20); DBGFPF((stderr, "OP_HANG: done sleeping\n")); ENABLE_INTERRUPTS(INTRPT_NO_TIMER_EVENTS); return; } if (WBTEST_ENABLED(WBTEST_BREAKMPC)&& (0 == gtm_white_box_test_case_count) && (999 == ms)) { frame_pointer->old_frame_pointer->mpc = (unsigned char *)GTM64_ONLY(0xdeadbeef12345678) NON_GTM64_ONLY(0xdead1234); return; } if (WBTEST_ENABLED(WBTEST_UTIL_OUT_BUFFER_PROTECTION) && (0 == gtm_white_box_test_case_count) && (999 == ms)) { /* Upon seeing a .999s hang this white-box test launches a timer that pops with a period of * UTIL_OUT_SYSLOG_INTERVAL and prints a long message via util_out_ptr. */ start_timer((TID)&util_out_syslog_dump, UTIL_OUT_SYSLOG_INTERVAL, util_out_syslog_dump, 0, NULL); return; } # endif sys_get_curr_time(&cur_time); mv_zintcmd = find_mvstent_cmd(ZINTCMD_HANG, restart_pc, restart_ctxt, FALSE); if (!mv_zintcmd) add_int_to_abs_time(&cur_time, ms, &end_time); else { end_time = mv_zintcmd->mv_st_cont.mvs_zintcmd.end_or_remain; cur_time = sub_abs_time(&end_time, &cur_time); /* get remaing time to sleep */ if (0 <= cur_time.at_sec) ms = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000); else ms = 0; /* all done */ /* restore/pop previous zintcmd_active[ZINTCMD_HANG] hints */ TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_prior; TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_ctxt_prior; TAREF1(zintcmd_active, ZINTCMD_HANG).count--; assert(0 <= TAREF1(zintcmd_active, ZINTCMD_HANG).count); if (mv_chain == mv_zintcmd) POP_MV_STENT(); /* just pop if top of stack */ else { /* flag as not active */ mv_zintcmd->mv_st_cont.mvs_zintcmd.command = ZINTCMD_NOOP; mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_check = NULL; } if (0 == ms) return; /* done HANGing */ } # ifdef UNIX if (ms < 10) SLEEP_USEC(ms * 1000, TRUE); /* Finish the sleep if it is less than 10ms. */ else hiber_start(ms); # elif defined(VMS) time[0] = -time_low_ms(ms); time[1] = -time_high_ms(ms) - 1; efn_mask = (1 << efn_outofband | 1 << efn_timer); if (SS$_NORMAL != (status = sys$setimr(efn_timer, &time, NULL, &time, 0))) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$setimr"), CALLFROM, status); if (SS$_NORMAL != (status = sys$wflor(efn_outofband, efn_mask))) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$wflor"), CALLFROM, status); if (outofband) { if (SS$_WASCLR == (status = sys$readef(efn_timer, &efn_mask))) { if (SS$_NORMAL != (status = sys$cantim(&time, 0))) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$cantim"), CALLFROM, status); } else assertpro(SS$_WASSET == status); } # endif } else rel_quant(); if (outofband) { PUSH_MV_STENT(MVST_ZINTCMD); mv_chain->mv_st_cont.mvs_zintcmd.end_or_remain = end_time; mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_check = restart_ctxt; mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_check = restart_pc; /* save current information from zintcmd_active */ mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_prior = TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last; mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_prior = TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last; TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = restart_pc; TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last = restart_ctxt; TAREF1(zintcmd_active, ZINTCMD_HANG).count++; mv_chain->mv_st_cont.mvs_zintcmd.command = ZINTCMD_HANG; outofband_action(FALSE); } return; }
pwr_tUInt32 bck_WaitBackup ( void *context, pwr_tBoolean timeout) { pwr_tUInt32 sts; pwr_tObjid objid; pwr_tInt32 c; pwr_tTime t; pwr_tVaxTime tmo; pwr_tVaxTime tmptime; pwr_sClass_Backup_Conf *backup_confp; /* Backup_Conf object pointer */ $DESCRIPTOR (timeunitdsc, "0 0:0:0.1"); /* 0.1 second units */ int cycletime; #ifdef OS_ELN pwr_tInt32 res; pwr_tVaxTime *tmop; #endif #ifdef OS_VMS $DESCRIPTOR (efcname, BCK_EFC_NAME); #endif /* * Initialize */ #ifdef OS_ELN if (!areas_mapped) { BCK_MAP_AREAS; areas_mapped = TRUE; } #endif /* * Find the local Backup_Conf object */ sts = gdh_GetClassList (pwr_cClass_Backup_Conf, &objid); while (ODD (sts)) { sts = gdh_ObjidToPointer (objid, (pwr_tAddress *)&backup_confp); if (ODD (sts)) break; sts = gdh_GetNextObject (objid, &objid); } if (EVEN (sts)) return sts; /* Something wrong, quit */ /* * Pick up argument information */ if (context == NULL) time_GetTime(&t); else { t = *(pwr_tTime *)context; free (context); } #ifdef OS_ELN tmop = NULL; #else timed_out = FALSE; sts = sys$ascefc (BCK_EFC, &efcname, 0, 0); if (EVEN (sts)) lib$signal (sts); /* BUG */ #endif if (timeout) { cycletime = backup_confp->CycleSlow * 2; if (cycletime == 0) cycletime = BCK_DEFAULT_SLOW * 2; #ifdef OS_ELN tmo = eln$time_value (&timeunitdsc); #else sts = sys$bintim (&timeunitdsc, &tmo); if (EVEN (sts)) lib$signal (sts); /* BUG, should not happen */ #endif lib$mult_delta_time ( &cycletime, /* multiplier */ &tmo); /* delta_time (modified) */ sys$gettim (&tmptime); lib$add_times (&tmo, &tmptime, &tmo); /* Make absolute time */ #ifdef OS_ELN tmop = &tmo; #else sts = sys$setimr (BCK_WRITE_DONE, &tmo, &astrtn, 4711, 0); if (EVEN (sts)) lib$signal (sts); /* BUG */ #endif } /* * Loop, and wait for things to happen */ while (TRUE) { #ifdef OS_ELN ker$clear_event (NULL, bck_write_done); ker$wait_any (NULL, &res, tmop, bck_write_done); /* Check for timeout */ if (res == 0) return SS$_TIMEOUT; #else sts = sys$clref (BCK_WRITE_DONE); if (EVEN (sts)) lib$signal (sts); /* BUG */ sts = sys$waitfr (BCK_WRITE_DONE); if (EVEN (sts)) lib$signal (sts); /* BUG */ /* Check for timeout */ if (timed_out) return SS$_TIMEOUT; #endif /* Check if both cycles done */ if (time_Acomp(&backup_confp->ObjTimeSlow, &t) < 0) continue; if (time_Acomp(&backup_confp->ObjTimeFast, &t) < 0) continue; break; } /* Loop */ #ifdef OS_VMS sys$cantim (4711, 0); #endif return 1; /* Done. */ } /* bck_WaitBackup */
void ccp_close1(ccp_db_header *db) { ccp_db_header *db0, *db1; ccp_que_entry *que_ent; ccp_relque *que_hd; mem_list *ml_ptr, *ml_ptr_hold; sgmnt_addrs *csa; vms_gds_info *gds_info; unsigned char section_name[GLO_NAME_MAXLEN]; uint4 retadr[2], status, outaddrs[2]; struct dsc$descriptor_s name_dsc; if (ccp_stop) ccp_stop_ctr--; if (db->stale_in_progress) sys$cantim(&db->stale_timer_id, PSL$C_USER); ccp_quemin_adjust(CCP_CLOSE_REGION); sys$cantim(&db->tick_timer_id, PSL$C_USER); sys$cantim(&db->quantum_timer_id, PSL$C_USER); db->segment->nl->ccp_state = CCST_CLOSED; db->wmexit_requested = TRUE; /* ignore any blocking ASTs - already releasing */ gds_info = FILE_INFO(db->greg); if (JNL_ENABLED(db->glob_sec)) { if (db->segment->jnl != NULL && db->segment->jnl->channel != 0) { status = sys$setimr(0, delta_1_sec, ccp_close_timeout, &db->close_timer_id, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = ccp_enqw(EFN$C_ENF, LCK$K_EXMODE, &db->wm_iosb, LCK$M_CONVERT | LCK$M_NOQUEUE, NULL, 0, NULL, 0, NULL, PSL$C_USER, 0); if (status == SS$_NOTQUEUED) /* We're not the only node accessing the journal file */ jnl_file_close(db->greg, FALSE, FALSE); else { /***** Check error status here? *****/ if (db->segment->jnl->jnl_buff->before_images && db->segment->ti->curr_tn > db->segment->jnl->jnl_buff->epoch_tn) { csa = db->segment; JNL_SHORT_TIME(jgbl.gbl_jrec_time); /* needed for jnl_put_jrt_pini() and jnl_write_epoch_rec() */ if (0 == csa->jnl->pini_addr) jnl_put_jrt_pini(csa); db->segment->jnl->jnl_buff->epoch_tn = db->segment->ti->curr_tn; jnl_write_epoch_rec(db->segment); } jnl_file_close(db->greg, TRUE, FALSE); } sys$cantim(&db->close_timer_id, PSL$C_USER); status = gtm_deq(gds_info->s_addrs.jnl->jnllsb->lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ } } db->segment = NULL; /* Warn AST's that the segment has been deleted */ status = sys$deq(db->lock_iosb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); if (status != SS$_NORMAL && status != SS$_CANCELGRANT) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$deq(db->refcnt_iosb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); if (status != SS$_NORMAL && status != SS$_CANCELGRANT) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$deq(db->wm_iosb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); if (status != SS$_NORMAL && status != SS$_CANCELGRANT) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$deq(db->flush_iosb.lockid, NULL, PSL$C_USER, LCK$M_CANCEL); if (status != SS$_NORMAL && status != SS$_CANCELGRANT) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$cancel(gds_info->fab->fab$l_stv); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$dassgn(gds_info->fab->fab$l_stv); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ csa = &gds_info->s_addrs; outaddrs[0] = csa->db_addrs[0] - OS_PAGE_SIZE; /* header no access page */ outaddrs[1] = csa->db_addrs[1] + OS_PAGE_SIZE; /* trailer no access page */ if (FALSE == is_va_free(outaddrs[0])) gtm_deltva(outaddrs, NULL, PSL$C_USER); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = sys$cretva(csa->db_addrs, retadr, PSL$C_USER); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ assert(retadr[0] == csa->db_addrs[0] && retadr[1] == csa->db_addrs[1]); ml_ptr_hold=db->mem_ptr; if (ml_ptr_hold->prev != NULL) { /* if prior segment is adjacent and free, coalesce the segments */ if (ml_ptr_hold->prev->free && ml_ptr_hold->addr == ml_ptr_hold->prev->addr + OS_PAGELET_SIZE * ml_ptr_hold->prev->pages) { ml_ptr = ml_ptr_hold->prev; ml_ptr->next = ml_ptr_hold->next; if (ml_ptr->next != NULL) ml_ptr->next->prev = ml_ptr; ml_ptr->pages += ml_ptr_hold->pages; free(ml_ptr_hold); ml_ptr_hold = ml_ptr; } } if (ml_ptr_hold->next != NULL) { /* if next segment is adjacent and free, coalesce the segments */ if (ml_ptr_hold->next->free && ml_ptr_hold->next->addr == ml_ptr_hold->addr + OS_PAGELET_SIZE * ml_ptr_hold->pages) { ml_ptr = ml_ptr_hold->next; ml_ptr_hold->next = ml_ptr->next; if (ml_ptr_hold->next != NULL) ml_ptr_hold->next->prev = ml_ptr_hold; ml_ptr_hold->pages += ml_ptr->pages; free(ml_ptr); } } ml_ptr_hold->free = TRUE; global_name("GT$S", &gds_info->file_id, section_name); name_dsc.dsc$a_pointer = §ion_name[1]; name_dsc.dsc$w_length = section_name[0]; name_dsc.dsc$b_dtype = DSC$K_DTYPE_T; name_dsc.dsc$b_class = DSC$K_CLASS_S; status = del_sec(SEC$M_SYSGBL, &name_dsc, NULL); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ /* Dequeue locks after delete section in ccp_close, acquire lock before create section in gvcst_init, release lock after delete section in gds_rundown */ status = gtm_deq(db->lock_iosb.lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = gtm_deq(db->refcnt_iosb.lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = gtm_deq(db->wm_iosb.lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ status = gtm_deq(db->flush_iosb.lockid, NULL, PSL$C_USER, 0); if (status != SS$_NORMAL) ccp_signal_cont(status); /***** Is this reasonable? *****/ que_hd = &ccp_action_que[PRIORITY]; for (que_ent = (char *)que_hd + que_hd->bl; que_ent != que_hd; que_ent = (char *)que_ent + que_ent->q.bl) if (que_ent->value.v.h == db) que_ent->value.v.h = 0; free(gds_info->fab->fab$l_nam); free(gds_info->fab); free(db->greg->dyn.addr); free(db->greg); /* Remove db from list, this list should never be changed in an AST */ for (db0 = ccp_reg_root, db1 = NULL; db0 != db; db1 = db0, db0 = db0->next) ; if (db1 == NULL) ccp_reg_root = db0->next; else db1->next = db0->next; free(db); return; }