Esempio n. 1
0
File: main.c Progetto: Sciumo/minix
/*===========================================================================*
 *			       do_pending_pipe				     *
 *===========================================================================*/
static void *do_pending_pipe(void *arg)
{
  int r, op;
  struct job my_job;
  struct filp *f;
  tll_access_t locktype;

  my_job = *((struct job *) arg);
  fp = my_job.j_fp;

  lock_proc(fp, 1 /* force lock */);

  f = scratch(fp).file.filp;
  assert(f != NULL);
  scratch(fp).file.filp = NULL;

  locktype = (job_call_nr == READ) ? VNODE_READ : VNODE_WRITE;
  op = (job_call_nr == READ) ? READING : WRITING;
  lock_filp(f, locktype);

  r = rw_pipe(op, who_e, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes);

  if (r != SUSPEND)  /* Do we have results to report? */
	reply(fp->fp_endpoint, r);

  unlock_filp(f);

  thread_cleanup(fp);
  return(NULL);
}
Esempio n. 2
0
File: misc.c Progetto: Hooman3/minix
/*===========================================================================*
 *				do_fsync				     *
 *===========================================================================*/
int do_fsync(void)
{
/* Perform the fsync() system call. */
  struct filp *rfilp;
  struct vmnt *vmp;
  dev_t dev;
  int r = OK;

  scratch(fp).file.fd_nr = job_m_in.m_lc_vfs_fsync.fd;

  if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
	return(err_code);

  dev = rfilp->filp_vno->v_dev;
  unlock_filp(rfilp);

  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
	if (vmp->m_dev != dev) continue;
	if ((r = lock_vmnt(vmp, VMNT_READ)) != OK)
		break;
	if (vmp->m_dev != NO_DEV && vmp->m_dev == dev &&
		vmp->m_fs_e != NONE && vmp->m_root_node != NULL) {

		req_sync(vmp->m_fs_e);
	}
	unlock_vmnt(vmp);
  }

  return(r);
}
Esempio n. 3
0
	/*! @brief suppress non-maximal candidates
	 *
	 * Given a vector of candidates, keep only the maximal candidates which
	 * overlap less than a defined fractional area. If overlap is 0.0 (the
	 * default value) no overlap is allowed. If, for example, the overlap is
	 * 0.2, then two candidates' bounding boxes can intersect by 20%
	 *
	 * @param im the input image from which the candidates were found
	 * @param candidates the vector of candidates
	 * @param overlap the allowable overlap [0.0 1.0)
	 */
	static void nonMaximaSuppression(const cv::Mat& im, vectorCandidate& candidates, const float overlap=0.0f) {

		// create a scratch space that we can draw on
		const unsigned int N = candidates.size();
		const cv::Rect bounds = cv::Rect(0,0,0,0) + im.size();
		cv::Mat scratch = cv::Mat::zeros(im.size(), CV_8U);

		// the current insertion position in the vector
		unsigned int keep = 0;

		/* iterate through the boxes, checking:
		 * 1) has the area under the box been painted?
		 * 2) if so, is it under the threshold?
		 * 3) if so, keep this box and paint the area
		 * 4) repeat
		 */
		for (unsigned int n = 0; n < N; ++n) {
			cv::Rect box = candidates[n].boundingBox() & bounds;
			cv::Scalar boxsum = sum(scratch(box));
			if (boxsum[0] / box.area() > overlap) continue;
			scratch(box) = 1;
			candidates[keep] = candidates[n];
			keep++;
		}

		// simply delete the trailing end of the candidates
		candidates.resize(keep);
	}
Esempio n. 4
0
/*===========================================================================*
 *				do_close				     *
 *===========================================================================*/
int do_close()
{
/* Perform the close(fd) system call. */

  scratch(fp).file.fd_nr = job_m_in.fd;
  return close_fd(fp, scratch(fp).file.fd_nr);
}
Esempio n. 5
0
void main()
{
    reset_scratch();
    scratch ("This is bad ..\n"); 
    dump_scratched_to (stdout, "# ");
    /* reset_scratch(); */
    scratch ("This is worse.\n");
    dump_scratched_to (stdout, "# ");
    /* kill_scratch(); */
    reset_scratch();
    scratch ("This is better\n");
    dump_scratched_to (stdout, "# ");
    reset_scratch();
    dump_scratched_to (stdout, "# ");
}
Esempio n. 6
0
/*===========================================================================*
 *				do_dup					     *
 *===========================================================================*/
int do_dup()
{
/* Perform the dup(fd) or dup2(fd,fd2) system call. These system calls are
 * obsolete.  In fact, it is not even possible to invoke them using the
 * current library because the library routines call fcntl().  They are
 * provided to permit old binary programs to continue to run.
 */

  int rfd, rfd2;
  struct filp *f;
  int r = OK;

  scratch(fp).file.fd_nr = job_m_in.fd;
  rfd2 = job_m_in.fd2;

  /* Is the file descriptor valid? */
  rfd = scratch(fp).file.fd_nr & ~DUP_MASK;	/* kill off dup2 bit, if on */
  if ((f = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);

  /* Distinguish between dup and dup2. */
  if (!(scratch(fp).file.fd_nr & DUP_MASK)) {		/* bit not on */
	/* dup(fd) */
	r = get_fd(0, 0, &rfd2, NULL);
  } else {
	/* dup2(old_fd, new_fd) */
	if (rfd2 < 0 || rfd2 >= OPEN_MAX) {
		r = EBADF;
	} else if (rfd == rfd2) {	/* ignore the call: dup2(x, x) */
		r = rfd2;
	} else {
		/* All is fine, close new_fd if necessary */
		unlock_filp(f);		/* or it might deadlock on do_close */
		(void) close_fd(fp, rfd2);	/* cannot fail */
		f = get_filp(rfd, VNODE_READ); /* lock old_fd again */
	}
  }

  if (r == OK) {
	/* Success. Set up new file descriptors. */
	f->filp_count++;
	fp->fp_filp[rfd2] = f;
	FD_SET(rfd2, &fp->fp_filp_inuse);
	r = rfd2;
  }

  unlock_filp(f);
  return(r);
}
Esempio n. 7
0
boost::optional<double> ClarkLoop::Run(ImageSet& convolvedResidual, const ao::uvector<const double*>& doubleConvolvedPsfs)
{
	_clarkModel = ClarkModel(_width, _height);
	
	findPeakPositions(convolvedResidual);
	
	_clarkModel.MakeSets(convolvedResidual);
	if(!_rmsFactorImage.empty())
		_clarkModel.MakeRMSFactorImage(_rmsFactorImage);
	Logger::Debug << "Number of components selected > " << _threshold << ": " << _clarkModel.size() << '\n';
	
	if(_clarkModel.size() == 0)
		return boost::optional<double>();
	
	ao::uvector<double> scratch(_clarkModel.size());
	double maxValue;
	size_t maxComponent = _clarkModel.GetMaxComponent(scratch.data(), maxValue, _allowNegativeComponents);
		
	while(std::fabs(maxValue) > _threshold && _currentIteration < _maxIterations && (!_stopOnNegativeComponent || maxValue>=0.0))
	{
		ao::uvector<double> componentValues(_clarkModel.Residual().size());
		for(size_t imgIndex=0; imgIndex!=_clarkModel.Residual().size(); ++imgIndex)
			componentValues[imgIndex] = _clarkModel.Residual()[imgIndex][maxComponent] * _gain;
		_fluxCleaned += maxValue * _gain;
		
		if(_fitter)
			_fitter->FitAndEvaluate(componentValues.data());
			
		for(size_t imgIndex=0; imgIndex!=_clarkModel.Model().size(); ++imgIndex)
			_clarkModel.Model()[imgIndex][maxComponent] += componentValues[imgIndex];
		
		size_t
			x = _clarkModel.X(maxComponent),
			y = _clarkModel.Y(maxComponent);
		/*
		  Commented out because even in verbose mode this is a bit too verbose, but useful in case divergence occurs:
		Logger::Debug << x << ", " << y << " " << maxValue << " -> ";
		for(size_t imgIndex=0; imgIndex!=_clarkModel.Model().size(); ++imgIndex)
		  Logger::Debug << componentValues[imgIndex] << ' ';
		Logger::Debug << '\n';
		*/
		for(size_t imgIndex=0; imgIndex!=_clarkModel.Residual().size(); ++imgIndex)
		{
			double* image = _clarkModel.Residual()[imgIndex];
			const double* psf = doubleConvolvedPsfs[_clarkModel.Residual().PSFIndex(imgIndex)];
			double psfFactor = componentValues[imgIndex];
			for(size_t px=0; px!=_clarkModel.size(); ++px)
			{
				int psfX = _clarkModel.X(px) - x + _width/2;
				int psfY = _clarkModel.Y(px) - y + _height/2;
				if(psfX >= 0 && psfX < int(_width) && psfY >= 0 && psfY < int(_height))
					image[px] -= psf[psfX + psfY*_width] * psfFactor;
			}
		}
		
		maxComponent = _clarkModel.GetMaxComponent(scratch.data(), maxValue, _allowNegativeComponents);
		++_currentIteration;
	}
	return maxValue;
}
void CompMod(ZZ_pX& x, const ZZ_pX& g, const ZZ_pXArgument& A, 
             const ZZ_pXModulus& F)
{
   if (deg(g) <= 0) {
      x = g;
      return;
   }


   ZZ_pX s, t;
   ZZVec scratch(F.n, ZZ_p::ExtendedModulusSize());

   long m = A.H.length() - 1;
   long l = ((g.rep.length()+m-1)/m) - 1;

   ZZ_pXMultiplier M;
   build(M, A.H[m], F);

   InnerProduct(t, g.rep, l*m, l*m + m - 1, A.H, F.n, scratch);
   for (long i = l-1; i >= 0; i--) {
      InnerProduct(s, g.rep, i*m, i*m + m - 1, A.H, F.n, scratch);
      MulMod(t, t, M, F);
      add(t, t, s);
   }

   x = t;
}
Esempio n. 9
0
void acceleratet::set_dirty_vars(path_acceleratort &accelerator)
{
  for(std::set<exprt>::iterator it=accelerator.dirty_vars.begin();
      it!=accelerator.dirty_vars.end();
      ++it)
  {
    expr_mapt::iterator jt=dirty_vars_map.find(*it);
    exprt dirty_var;

    if(jt==dirty_vars_map.end())
    {
      scratch_programt scratch(symbol_table);
      symbolt new_sym=utils.fresh_symbol("accelerate::dirty", bool_typet());
      dirty_var=new_sym.symbol_expr();
      dirty_vars_map[*it]=dirty_var;
    }
    else
    {
      dirty_var=jt->second;
    }

#ifdef DEBUG
    std::cout << "Setting dirty flag " << expr2c(dirty_var, ns)
      << " for " << expr2c(*it, ns) << '\n';
#endif

    accelerator.pure_accelerator.add_instruction(ASSIGN)->code =
      code_assignt(dirty_var, true_exprt());
  }
}
Esempio n. 10
0
void CompMod(zz_pX& x, const zz_pX& g, const zz_pXArgument& A, 
             const zz_pXModulus& F)
{
   if (deg(g) <= 0) {
      x = g;
      return;
   }


   zz_pX s, t;
   vec_zz_p scratch(INIT_SIZE, F.n);

   long m = A.H.length() - 1;
   long l = ((g.rep.length()+m-1)/m) - 1;

   zz_pXMultiplier M;
   build(M, A.H[m], F);

   InnerProduct(t, g.rep, l*m, l*m + m - 1, A.H, F.n, scratch);
   for (long i = l-1; i >= 0; i--) {
      InnerProduct(s, g.rep, i*m, i*m + m - 1, A.H, F.n, scratch);
      MulMod(t, t, M, F);
      add(t, t, s);
   }

   x = t;
}
Esempio n. 11
0
/**
 * Merge config 'c' into this config, preserving this config's values.
 */
void config::inherit_from(const config& c)
{
	// Using a scratch config and merge_with() seems to execute about as fast
	// as direct coding of this merge.
	config scratch(c);
	scratch.merge_with(*this);
	swap(scratch);
}
Esempio n. 12
0
void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transform) {
	if (mode == PhysicsServer::BODY_MODE_KINEMATIC) {
		if (space)
			btBody->setLinearVelocity((p_global_transform.getOrigin() - btBody->getWorldTransform().getOrigin()) / space->get_delta_time());
		// The kinematic use MotionState class
		godotMotionState->moveBody(p_global_transform);
	}
	btBody->setWorldTransform(p_global_transform);
	scratch();
}
Esempio n. 13
0
/*===========================================================================*
 *				do_getdents				     *
 *===========================================================================*/
int do_getdents(void)
{
/* Perform the getdents(fd, buf, size) system call. */
  int r = OK;
  off_t new_pos;
  register struct filp *rfilp;

  scratch(fp).file.fd_nr = job_m_in.m_lc_vfs_readwrite.fd;
  scratch(fp).io.io_buffer = job_m_in.m_lc_vfs_readwrite.buf;
  scratch(fp).io.io_nbytes = job_m_in.m_lc_vfs_readwrite.len;

  /* Is the file descriptor valid? */
  if ( (rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
	return(err_code);

  if (!(rfilp->filp_mode & R_BIT))
	r = EBADF;
  else if (!S_ISDIR(rfilp->filp_vno->v_mode))
	r = EBADF;

  if (r == OK) {
	r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
			 rfilp->filp_pos, scratch(fp).io.io_buffer,
			 scratch(fp).io.io_nbytes, &new_pos, 0);

	if (r > 0) rfilp->filp_pos = new_pos;
  }

  unlock_filp(rfilp);
  return(r);
}
Esempio n. 14
0
Array<T> dot(const Array<T> &lhs, const Array<T> &rhs,
             af_blas_transpose optLhs, af_blas_transpose optRhs)
{
    initBlas();

    int N = lhs.dims()[0];
    dot_func<T> dot;
    cl::Event event;
    auto out = createEmptyArray<T>(af::dim4(1));
    cl::Buffer scratch(getContext(), CL_MEM_READ_WRITE, sizeof(T) * N);
    clblasStatus err;
    err = dot(N,
              (*out.get())(), out.getOffset(),
              (*lhs.get())(),  lhs.getOffset(), lhs.strides()[0],
              (*rhs.get())(),  rhs.getOffset(), rhs.strides()[0],
              scratch(),
              1, &getQueue()(), 0, nullptr, &event());

    if(err) {
        throw runtime_error(std::string("CLBLAS error: ") + std::to_string(err));
    }
    return out;
}
Esempio n. 15
0
typename std::iterator_traits<Iterator>::value_type reduce(
    ExecutionPolicy &sep, Iterator b, Iterator e, T init, BinaryOperation bop) {
  cl::sycl::queue q(sep.get_queue());
  auto vectorSize = std::distance(b, e);

  if (vectorSize < 1) {
    return init;
  }

  auto device = q.get_device();
  auto local = device.get_info<cl::sycl::info::device::max_work_group_size>();
  typedef typename std::iterator_traits<Iterator>::value_type type_;
  auto bufI = sycl::helpers::make_const_buffer(b, e);
  size_t length = vectorSize;
  size_t global = sep.calculateGlobalSize(length, local);

  do {
    auto f = [length, local, global, &bufI, bop](cl::sycl::handler &h) mutable {
      cl::sycl::nd_range<3> r{cl::sycl::range<3>{std::max(global, local), 1, 1},
                              cl::sycl::range<3>{local, 1, 1}};
      auto aI = bufI.template get_access<cl::sycl::access::mode::read_write>(h);
      cl::sycl::accessor<type_, 1, cl::sycl::access::mode::read_write,
                         cl::sycl::access::target::local>
          scratch(cl::sycl::range<1>(local), h);

      h.parallel_for<typename ExecutionPolicy::kernelName>(
          r, [aI, scratch, local, length, bop](cl::sycl::nd_item<3> id) {
            int globalid = id.get_global(0);
            int localid = id.get_local(0);

            auto r = ReductionStrategy<T>(local, length, id, scratch);
            r.workitem_get_from(aI);
            r.combine_threads(bop);
            r.workgroup_write_to(aI);
          });
    };
    q.submit(f);
    length = length / local;
  } while (length > 1);
  q.wait_and_throw();
  auto hI = bufI.template get_access<cl::sycl::access::mode::read,
                                     cl::sycl::access::target::host_buffer>();
  return hI[0] + init;
}
Esempio n. 16
0
int tool_main(int argc, char** argv) {
    SkCommandLineFlags::Parse(argc, argv);
    SkAutoGraphics autoGraphics;

    // We share a single scratch bitmap among benches to reduce the profile noise from allocation.
    static const int kMaxArea = 209825221;  // tabl_mozilla is this big.
    SkAutoTMalloc<SkPMColor> scratch(kMaxArea);

    SkOSFile::Iter it(FLAGS_skps[0], ".skp");
    SkString filename;
    bool failed = false;
    while (it.next(&filename)) {
        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, filename.c_str())) {
            continue;
        }

        const SkString path = SkOSPath::SkPathJoin(FLAGS_skps[0], filename.c_str());

        SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path.c_str()));
        if (!stream) {
            SkDebugf("Could not read %s.\n", path.c_str());
            failed = true;
            continue;
        }
        SkAutoTUnref<SkPicture> src(SkPicture::CreateFromStream(stream));
        if (!src) {
            SkDebugf("Could not read %s as an SkPicture.\n", path.c_str());
            failed = true;
            continue;
        }

        if (src->width() * src->height() > kMaxArea) {
            SkDebugf("%s (%dx%d) is larger than hardcoded scratch bitmap (%dpx).\n",
                     path.c_str(), src->width(), src->height(), kMaxArea);
            failed = true;
            continue;
        }

        bench(scratch.get(), *src, filename.c_str());
    }
    return failed ? 1 : 0;
}
Esempio n. 17
0
  void dTdLMom2(const std::list<Minim::WPPoint> &l,
		Minim::ModelDesc &md,
		const WVRAtmoQuants &model,
		const double *m1,
		double Z,
		double thresh,
		double *res
		)
  {
    std::vector<double> scratch(4, 0.0);
    const double Pthresh= Z*thresh;
    for(size_t i=0; i<4; ++i)
      res[i]=0;

    for(std::list<Minim::WPPoint>::const_iterator i=l.begin();
	i!= l.end();
	++i)
    {
      const double w=i->w *exp(- i->ll);
      if (w > Pthresh)
      {
	md.put(i->p);
	model.dTdL_ND(scratch);
	for(size_t j=0; j<scratch.size(); ++j)
	{
	  res[j]+=std::pow(scratch[j]-m1[j],2)*w;
	}
      }
    }
    if(Z==0.) 
    {
      std::cout << "Error: Cannot calculate dTdL Moment 2, evidence is zero." << std::endl;
      std::cerr << "Error: Cannot calculate dTdL Moment 2, evidence is zero." << std::endl;
    }
    else
    {
      for(size_t j=0; j<scratch.size(); ++j) 
      {
	res[j]/=Z;
      }
    }
  }
TEST_F(MTK_Kokkos, calculate_centroid_field_with_gather_on_device_flat)
{
    MyApp app;

    GpuGatherFlatScratchData scratch(app.choice);
    scratch.initialize(*app.bulk, *app.coords, app.centroid, app.meta.locally_owned_part());

    CentroidCalculator<GpuGatherFlatScratchData> calculator(scratch);
    
    app.start_timer();
    calculator.calculate_centroids(app.num_repeat, app.choice, app.teamSize);
    app.stop_timer();
    app.report_bandwidth();

    calculator.copy_centroids_to_host();
//    calculator.test_centroid_of_element_1();

    for(unsigned elementIndex=0; elementIndex<scratch.hostElemEntities.extent(0); ++elementIndex) {
        calculator.test_centroid_of_element(app.hostCentroid, scratch.hostElemEntities(elementIndex), elementIndex);
    }
}
Esempio n. 19
0
/*===========================================================================*
 *				actual_read_write_peek			     *
 *===========================================================================*/
int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd,
	vir_bytes io_buf, size_t io_nbytes)
{
/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
  struct filp *f;
  tll_access_t locktype;
  int r;
  int ro = 1;

  if(rw_flag == WRITING) ro = 0;

  scratch(rfp).file.fd_nr = io_fd;
  scratch(rfp).io.io_buffer = io_buf;
  scratch(rfp).io.io_nbytes = io_nbytes;

  locktype = rw_flag == WRITING ? VNODE_WRITE : VNODE_READ;
  if ((f = get_filp2(rfp, scratch(rfp).file.fd_nr, locktype)) == NULL)
	return(err_code);

  assert(f->filp_count > 0);

  if (((f->filp_mode) & (ro ? R_BIT : W_BIT)) == 0) {
	unlock_filp(f);
	return(EBADF);
  }
  if (scratch(rfp).io.io_nbytes == 0) {
	unlock_filp(f);
	return(0);	/* so char special files need not check for 0*/
  }

  r = read_write(rfp, rw_flag, f, scratch(rfp).io.io_buffer,
	scratch(rfp).io.io_nbytes, who_e);

  unlock_filp(f);
  return(r);
}
Esempio n. 20
0
void AreaBullet::add_overlap(CollisionObjectBullet *p_otherObject) {
	scratch();
	overlappingObjects.push_back(OverlappingObjectData(p_otherObject, OVERLAP_STATE_ENTER));
	p_otherObject->notify_new_overlap(this);
}
Esempio n. 21
0
File: misc.c Progetto: Hooman3/minix
/*===========================================================================*
 *				do_fcntl				     *
 *===========================================================================*/
int do_fcntl(void)
{
/* Perform the fcntl(fd, cmd, ...) system call. */

  register struct filp *f;
  int new_fd, fl, r = OK, fcntl_req, fcntl_argx;
  tll_access_t locktype;

  scratch(fp).file.fd_nr = job_m_in.m_lc_vfs_fcntl.fd;
  scratch(fp).io.io_buffer = job_m_in.m_lc_vfs_fcntl.arg_ptr;
  scratch(fp).io.io_nbytes = job_m_in.m_lc_vfs_fcntl.cmd;
  fcntl_req = job_m_in.m_lc_vfs_fcntl.cmd;
  fcntl_argx = job_m_in.m_lc_vfs_fcntl.arg_int;

  /* Is the file descriptor valid? */
  locktype = (fcntl_req == F_FREESP) ? VNODE_WRITE : VNODE_READ;
  if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
	return(err_code);

  switch (fcntl_req) {
    case F_DUPFD:
	/* This replaces the old dup() system call. */
	if (fcntl_argx < 0 || fcntl_argx >= OPEN_MAX) r = EINVAL;
	else if ((r = get_fd(fp, fcntl_argx, 0, &new_fd, NULL)) == OK) {
		f->filp_count++;
		fp->fp_filp[new_fd] = f;
		r = new_fd;
	}
	break;

    case F_GETFD:
	/* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	r = 0;
	if (FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set))
		r = FD_CLOEXEC;
	break;

    case F_SETFD:
	/* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	if (fcntl_argx & FD_CLOEXEC)
		FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
	else
		FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
	break;

    case F_GETFL:
	/* Get file status flags (O_NONBLOCK and O_APPEND). */
	fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
	r = fl;
	break;

    case F_SETFL:
	/* Set file status flags (O_NONBLOCK and O_APPEND). */
	fl = O_NONBLOCK | O_APPEND;
	f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
	break;

    case F_GETLK:
    case F_SETLK:
    case F_SETLKW:
	/* Set or clear a file lock. */
	r = lock_op(f, fcntl_req);
	break;

    case F_FREESP:
     {
	/* Free a section of a file */
	off_t start, end, offset;
	struct flock flock_arg;

	/* Check if it's a regular file. */
	if (!S_ISREG(f->filp_vno->v_mode)) r = EINVAL;
	else if (!(f->filp_mode & W_BIT)) r = EBADF;
	else {
		/* Copy flock data from userspace. */
		r = sys_datacopy_wrapper(who_e, scratch(fp).io.io_buffer,
			SELF, (vir_bytes) &flock_arg, sizeof(flock_arg));
	}

	if (r != OK) break;

	/* Convert starting offset to signed. */
	offset = (off_t) flock_arg.l_start;

	/* Figure out starting position base. */
	switch(flock_arg.l_whence) {
	  case SEEK_SET: start = 0; break;
	  case SEEK_CUR: start = f->filp_pos; break;
	  case SEEK_END: start = f->filp_vno->v_size; break;
	  default: r = EINVAL;
	}
	if (r != OK) break;

	/* Check for overflow or underflow. */
	if (offset > 0 && start + offset < start) r = EINVAL;
	else if (offset < 0 && start + offset > start) r = EINVAL;
	else {
		start += offset;
		if (start < 0) r = EINVAL;
	}
	if (r != OK) break;

	if (flock_arg.l_len != 0) {
		if (start >= f->filp_vno->v_size) r = EINVAL;
		else if ((end = start + flock_arg.l_len) <= start) r = EINVAL;
		else if (end > f->filp_vno->v_size) end = f->filp_vno->v_size;
	} else {
                end = 0;
	}
	if (r != OK) break;

	r = req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr,start,end);

	if (r == OK && flock_arg.l_len == 0)
		f->filp_vno->v_size = start;

	break;
     }
    case F_GETNOSIGPIPE:
	r = !!(f->filp_flags & O_NOSIGPIPE);
	break;
    case F_SETNOSIGPIPE:
	if (fcntl_argx)
		f->filp_flags |= O_NOSIGPIPE;
	else
		f->filp_flags &= ~O_NOSIGPIPE;
	break;
    case F_FLUSH_FS_CACHE:
    {
	struct vnode *vn = f->filp_vno;
	mode_t mode = f->filp_vno->v_mode;
	if (!super_user) {
		r = EPERM;
	} else if (S_ISBLK(mode)) {
		/* Block device; flush corresponding device blocks. */
		r = req_flush(vn->v_bfs_e, vn->v_sdev);
	} else if (S_ISREG(mode) || S_ISDIR(mode)) {
		/* Directory or regular file; flush hosting FS blocks. */
		r = req_flush(vn->v_fs_e, vn->v_dev);
	} else {
		/* Remaining cases.. Meaning unclear. */
		r = ENODEV;
	}
	break;
    }
    default:
	r = EINVAL;
  }

  unlock_filp(f);
  return(r);
}
Esempio n. 22
0
void AreaBullet::put_overlap_as_exit(int p_index) {
	scratch();
	overlappingObjects.write[p_index].state = OVERLAP_STATE_EXIT;
}
Esempio n. 23
0
/*===========================================================================*
 *				do_unlink				     *
 *===========================================================================*/
int do_unlink()
{
/* Perform the unlink(name) or rmdir(name) system call. The code for these two
 * is almost the same.  They differ only in some condition testing.  Unlink()
 * may be used by the superuser to do dangerous things; rmdir() may not.
 * The syscall might provide 'name' embedded in the message.
 */
  struct vnode *dirp, *dirp_l, *vp;
  struct vmnt *vmp, *vmp2;
  int r;
  char fullpath[PATH_MAX];
  struct lookup resolve, stickycheck;
  vir_bytes vname;
  size_t vname_length;

  vname = (vir_bytes) job_m_in.name;
  vname_length = job_m_in.name_length;
  if (copy_name(vname_length, fullpath) != OK) {
	/* Direct copy failed, try fetching from user space */
	if (fetch_name(vname, vname_length, fullpath) != OK)
		/* CSC2025 Mod Start */
		logfserr_nopath(FSOP_UNLNK, err_code);
		/* CSC2025 Mod End */
		return(err_code);
  }

  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &dirp_l);
  resolve.l_vmnt_lock = VMNT_WRITE;
  resolve.l_vnode_lock = VNODE_WRITE;

  /* Get the last directory in the path. */
  if ((dirp = last_dir(&resolve, fp)) == NULL){
	  /* CSC2025 Mod Start */
	  logfserr_nopath(FSOP_UNLNK, err_code);
	  /* CSC2025 Mod End */
	  return(err_code)
  };

  /* Make sure that the object is a directory */
  if (!S_ISDIR(dirp->v_mode)) {
	unlock_vnode(dirp);
	unlock_vmnt(vmp);
	put_vnode(dirp);
	/* CSC2025 Mod Start */
	logfserr_nopath(FSOP_UNLNK, ENOTDIR);
	/* CSC2025 Mod End */
	return(ENOTDIR);
  }

  /* The caller must have both search and execute permission */
  if ((r = forbidden(fp, dirp, X_BIT | W_BIT)) != OK) {
	unlock_vnode(dirp);
	unlock_vmnt(vmp);
	put_vnode(dirp);
	/* CSC2025 Mod Start */
	logfserr(FSOP_UNLNK, r, fullpath);
	/* CSC2025 Mod End */
	return(r);
  }

  /* Also, if the sticky bit is set, only the owner of the file or a privileged
     user is allowed to unlink */
  if ((dirp->v_mode & S_ISVTX) == S_ISVTX) {
	/* Look up inode of file to unlink to retrieve owner */
	lookup_init(&stickycheck, resolve.l_path, PATH_RET_SYMLINK, &vmp2, &vp);
	stickycheck.l_vmnt_lock = VMNT_READ;
	stickycheck.l_vnode_lock = VNODE_READ;
	vp = advance(dirp, &stickycheck, fp);
	assert(vmp2 == NULL);
	if (vp != NULL) {
		if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
			r = EPERM;
		unlock_vnode(vp);
		put_vnode(vp);
	} else
		r = err_code;
	if (r != OK) {
		unlock_vnode(dirp);
		unlock_vmnt(vmp);
		put_vnode(dirp);
		/* CSC2025 Mod Start */
		logfserr(FSOP_UNLNK, r, fullpath);
		/* CSC2025 Mod End */
		return(r);
	}
  }

  upgrade_vmnt_lock(vmp);

  if (job_call_nr == UNLINK)
	  r = req_unlink(dirp->v_fs_e, dirp->v_inode_nr, fullpath);
  else
	  r = req_rmdir(dirp->v_fs_e, dirp->v_inode_nr, fullpath);
  unlock_vnode(dirp);
  unlock_vmnt(vmp);
  put_vnode(dirp);
  /* CSC2025 Mod Start */
  if(r == OK){
	  logfsop(FSOP_UNLNK, r, fullpath, scratch(fp).file.fd_nr, vp->v_mode, vp->v_uid, vp->v_gid, vp->v_size};
  } else {
Esempio n. 24
0
bool equal(ExecutionPolicy& exec, ForwardIt1 first1, ForwardIt1 last1,
           ForwardIt2 first2, ForwardIt2 last2, BinaryPredicate p) {
  cl::sycl::queue q(exec.get_queue());

  auto size1 = sycl::helpers::distance(first1, last1);
  auto size2 = sycl::helpers::distance(first2, last2);

  if (size1 != size2) {
    return false;
  }

  if (size1 < 1) {
    return true;
  }

  auto device = q.get_device();

  auto length = size1;
  auto ndRange = exec.calculateNdRange(size1);
  const auto local = ndRange.get_local_range()[0];

  auto buf1 = sycl::helpers::make_const_buffer(first1, last1);
  auto buf2 = sycl::helpers::make_const_buffer(first2, last2);
  auto bufR = cl::sycl::buffer<bool, 1>(cl::sycl::range<1>(size1));

  do {
    int passes = 0;

    auto f = [passes, length, ndRange, local, &buf1, &buf2, &bufR,
              p](cl::sycl::handler& h) mutable {
      auto a1 = buf1.template get_access<cl::sycl::access::mode::read>(h);
      auto a2 = buf2.template get_access<cl::sycl::access::mode::read>(h);
      auto aR = bufR.template get_access<cl::sycl::access::mode::read_write>(h);
      cl::sycl::accessor<bool, 1, cl::sycl::access::mode::read_write,
                         cl::sycl::access::target::local>
          scratch(ndRange.get_local_range(), h);

      h.parallel_for<typename ExecutionPolicy::kernelName>(
          ndRange, [a1, a2, aR, scratch, passes, local, length,
              p](cl::sycl::nd_item<1> id) {
            auto r =
                ReductionStrategy<bool>(local, length, id, scratch);
            if (passes == 0) {
              r.workitem_get_from(p, a1, a2);
            } else {
              r.workitem_get_from(aR);
            }
            r.combine_threads(std::logical_and<bool>{});
            r.workgroup_write_to(aR);
          });  // end kernel
    };         // end command group

    q.submit(f);
    length = length / local;
    ndRange = cl::sycl::nd_range<1>{cl::sycl::range<1>(std::max(length, local)),
                                    ndRange.get_local_range()};
    ++passes;
  } while (length > 1);
  q.wait_and_throw();
  auto hr = bufR.template get_access<cl::sycl::access::mode::read>(
      cl::sycl::range<1>{1}, cl::sycl::id<1>{0});
  return hr[0];
}
Esempio n. 25
0
int ExportQuake3Model(const TCHAR *filename, ExpInterface *ei, Interface *gi, int start_time, std::list<ExportNode> lTags, std::list<ExportNode> lMeshes)
{
	FILE *file;
	int i, j, totalTags, totalMeshes, current_time = 0;
	long pos_current, totalTris = 0, totalVerts = 0;
	std::list<FrameRange>::iterator range_i;
	std::vector<Point3> lFrameBBoxMin;
	std::vector<Point3> lFrameBBoxMax;
	long pos_tagstart;
	long pos_tagend;
	long pos_filesize;
	long pos_framestart;
	int lazynamesfixed = 0;
	const Point3 x_axis(1, 0, 0);
	const Point3 z_axis(0, 0, 1);

	SceneEnumProc checkScene(ei->theScene, start_time, gi);
	totalTags = (int)lTags.size();
	if (g_tag_for_pivot)
		totalTags++;
	totalMeshes = (int)lMeshes.size();

	// open file
	file = _tfopen(filename, _T("wb"));
	if (!file)
	{
		ExportError("Cannot open file '%s'.", filename);
		return FALSE;
	}
	ExportDebug("%s:", filename);

	// sync pattern and version
	putChars("IDP3", 4, file);
	put32(15, file);
	putChars("Darkplaces MD3 Exporter", 64, file);
	put32(0, file);   // flags
	
	// MD3 header
	ExportState("Writing MD3 header");
	put32(g_total_frames, file);      // how many frames
	put32(totalTags, file);	  // tagsnum
	put32(totalMeshes, file); // meshnum
	put32(1, file);   // maxskinnum
	put32(108, file); // headersize
	pos_tagstart = ftell(file); put32(0, file);   // tagstart
	pos_tagend	= ftell(file);  put32(256, file); // tagend
	pos_filesize = ftell(file); put32(512, file); // filesize
	ExportDebug("    %i frames, %i tags, %i meshes", g_total_frames, totalTags, totalMeshes);

	// frame info
	// bbox arrays get filled while exported mesh and written back then
	ExportState("Writing frame info");
	pos_framestart = ftell(file);
	lFrameBBoxMin.resize(g_total_frames);
	lFrameBBoxMax.resize(g_total_frames);
	for (i = 0; i < g_total_frames; i++)
	{
		// init frame data
		lFrameBBoxMin[i].Set(0, 0, 0);
		lFrameBBoxMax[i].Set(0, 0, 0);
		// put data
		putFloat(-1.0f, file); // bbox min vector
		putFloat(-1.0f, file);
		putFloat(-1.0f, file);	
		putFloat( 1.0f, file); // bbox max vector
		putFloat(1.0f, file);
		putFloat(1.0f, file);
		putFloat(0.0f, file);  // local origin (usually 0 0 0)
		putFloat(0.0f, file);
		putFloat(0.0f, file);
		putFloat(1.0f, file);  // radius of bounding sphere
		putChars("", 16, file);
	}

	// tags
	pos_current = ftell(file);
	fseek(file, pos_tagstart, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);
	
	// for each frame range cycle all frames and write out each tag
	long pos_tags = pos_current;
	if (totalTags)
	{
		long current_frame = 0;
		ExportState("Writing %i tags", totalTags);
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				SceneEnumProc current_scene(ei->theScene, i * g_ticks_per_frame, gi);
				current_time = current_scene.time;

				// write out tags
				if (lTags.size())
				{
					for (std::list<ExportNode>::iterator tag_i = lTags.begin(); tag_i != lTags.end(); tag_i++)
					{
						INode *node	= current_scene[tag_i->i]->node;
						Matrix3	tm = node->GetObjTMAfterWSM(current_time);

						ExportState("Writing '%s' frame %i of %i", tag_i->name, i, g_total_frames);

						// tagname
						putChars(tag_i->name, 64, file);
						// origin, rotation matrix
						Point3 row = tm.GetRow(3);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(0);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(1);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
						row = tm.GetRow(2);
						putFloat(row.x, file);
						putFloat(row.y, file);
						putFloat(row.z, file);
					}
				}

				// write the center of mass tag_pivot which is avg of all objects's pivots
				if (g_tag_for_pivot)
				{
					ExportState("Writing 'tag_pivot' frame %i of %i", i, g_total_frames);

					// write the null data as tag_pivot need to be written after actual geometry
					// (it needs information on frame bound boxes to get proper blendings)
					putChars("tag_pivot", 64, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(0, file);
					putFloat(1, file);
				}
			}
		}
	}

	// write the tag object offsets
	pos_current = ftell(file);
	fseek(file, pos_tagend, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);

	// allocate the structs used to calculate tag_pivot
	std::vector<Point3> tag_pivot_origin;
	std::vector<double> tag_pivot_volume;
	if (g_tag_for_pivot)
	{
		tag_pivot_origin.resize(g_total_frames);
		tag_pivot_volume.resize(g_total_frames);
	}

	// mesh objects
	// for each mesh object write uv and frames
	SceneEnumProc scratch(ei->theScene, start_time, gi);
	ExportState("Writing %i meshes", (int)lMeshes.size());
	for (std::list<ExportNode>::iterator mesh_i = lMeshes.begin(); mesh_i != lMeshes.end(); mesh_i++)
	{
		bool needsDel;

		ExportState("Start mesh #%i", mesh_i);
		INode *node = checkScene[mesh_i->i]->node;
		Matrix3 tm	= node->GetObjTMAfterWSM(start_time);
		TriObject *tri = GetTriObjectFromNode(node, start_time, needsDel);
		if (!tri)
			continue;

		// get mesh, compute normals
		Mesh &mesh = tri->GetMesh();
		MeshNormalSpec *meshNormalSpec = mesh.GetSpecifiedNormals();
		if (meshNormalSpec)
		{
			if (!meshNormalSpec->GetNumFaces())
				meshNormalSpec = NULL;
			else
			{
				meshNormalSpec->SetParent(&mesh);
				meshNormalSpec->CheckNormals();
			}
		}
		mesh.checkNormals(TRUE);

		// fix lazy object names
		ExportState("Attempt to fix mesh name '%s'", mesh_i->name);
		char  meshname[64];
		size_t meshnamelen = min(63, strlen(mesh_i->name));
		memset(meshname, 0, 64);
		strncpy(meshname, mesh_i->name, meshnamelen);
		meshname[meshnamelen] = 0;
		if (!strncmp("Box", meshname, 3)    || !strncmp("Sphere", meshname, 6)  || !strncmp("Cylinder", meshname, 8) ||
            !strncmp("Torus", meshname, 5)  || !strncmp("Cone", meshname, 4)    || !strncmp("GeoSphere", meshname, 9) ||
			!strncmp("Tube", meshname, 4)   || !strncmp("Pyramid", meshname, 7) || !strncmp("Plane", meshname, 5) ||
			!strncmp("Teapot", meshname, 6) || !strncmp("Object", meshname, 6))
		{
name_conflict:
			lazynamesfixed++;
			if (lazynamesfixed == 1)
				strcpy(meshname, "base");
			else
				sprintf(meshname, "base%i", lazynamesfixed);

			// check if it's not used by another mesh
			for (std::list<ExportNode>::iterator m_i = lMeshes.begin(); m_i != lMeshes.end(); m_i++)
				if (!strncmp(m_i->name, meshname, strlen(meshname)))
					goto name_conflict;
			// approve name
			ExportWarning("Lazy object name '%s' (mesh renamed to '%s').", node->GetName(), meshname);
		}

		// special mesh check
		bool shadow_or_collision = false;
		if (g_mesh_special)
			  if (!strncmp("collision", meshname, 9) || !strncmp("shadow", meshname, 6))
				shadow_or_collision = true;

		// get material
		const char *shadername = NULL;
		Texmap *tex = 0;
		Mtl *mtl = 0;
		if (!shadow_or_collision)
		{
			mtl = node->GetMtl();
			if (mtl)
			{
				// check for multi-material
				if (mtl->IsMultiMtl())
				{
					// check if it's truly multi material
					// we do support multi-material with only one texture (some importers set it)
					bool multi_material = false;
					MtlID matId = mesh.faces[0].getMatID();
					for (i = 1; i < mesh.getNumFaces(); i++)
						if (mesh.faces[i].getMatID() != matId)
							multi_material = true;

					if (multi_material)
						if (g_mesh_multimaterials == MULTIMATERIALS_NONE)
							ExportWarning("Object '%s' is multimaterial and using multiple materials on its faces, that case is not yet supported (truncating to first submaterial).", node->GetName());
					
					// switch to submaterial
					mtl = mtl->GetSubMtl(matId);
				}

				// get shader from material if supplied
				char *materialname = GetChar(mtl->GetName());
				if (g_mesh_materialasshader && (strstr(materialname, "/") != NULL || strstr(materialname, "\\") != NULL))
					shadername = GetChar(mtl->GetName());
				else
				{
					// get texture
					tex = mtl->GetSubTexmap(ID_DI);
					if (tex)
					{
						if (tex->ClassID() == Class_ID(BMTEX_CLASS_ID, 0x00))
						{
							shadername = GetChar(((BitmapTex *)tex)->GetMapName());
							if (shadername == NULL || !shadername[0])
								ExportWarning("Object '%s' material '%s' has no bitmap.", tex->GetName(), node->GetName());
						}
						else
						{
							tex = NULL;
							ExportWarning("Object '%s' has material with wrong texture type (only Bitmap are supported).", node->GetName());
						}
					}
					else
						ExportWarning("Object '%s' has material but no texture.", node->GetName());
				}
			}
			else
				ExportWarning("Object '%s' has no material.", node->GetName());
		}

		long pos_meshstart = ftell(file);

		// surface object
		ExportState("Writing mesh '%s' header", meshname);
		putChars("IDP3", 4, file);
		putChars(meshname, 64, file);
		put32(0, file); // flags
		put32(g_total_frames, file);                          // framecount
		put32(1, file);                                       // skincount
		long pos_vertexnum = ftell(file); put32(0, file);     // vertexcount
		put32(mesh.getNumFaces(), file);                      // trianglecount
		long pos_trianglestart = ftell(file); put32(0, file); // start triangles
		put32(108, file);                                     // header size
		long pos_texvecstart = ftell(file); put32(0, file);   // texvecstart
		long pos_vertexstart = ftell(file); put32(16, file);  // vertexstart
		long pos_meshsize = ftell(file); put32(32, file);	  // meshsize

		// write out a single 'skin'
		ExportState("Writing mesh %s texture", meshname);
		if (shadow_or_collision)
			putChars(meshname, 64, file);
		else if (shadername) 
			putMaterial(shadername, mtl, tex, file);
		else
			putChars("noshader", 64, file);
		put32(0, file); // flags

		// build geometry
		ExportState("Building vertexes/triangles");
		std::vector<ExportVertex>vVertexes;
		std::vector<ExportTriangle>vTriangles;
		vVertexes.resize(mesh.getNumVerts());
		int vExtraVerts = mesh.getNumVerts();
		for (i = 0; i < mesh.getNumVerts(); i++)
		{
			vVertexes[i].vert = i;
			vVertexes[i].normalfilled = false;
			// todo: check for coincident verts
		}
		int vNumExtraVerts = 0;

		// check normals
		if (!mesh.normalsBuilt && !shadow_or_collision)
			ExportWarning("Object '%s' does not have normals contructed.", node->GetName());

		// get info for triangles
		const float normal_epsilon = 0.01f;
		vTriangles.resize(mesh.getNumFaces());
		for (i = 0; i < mesh.getNumFaces(); i++)
		{
			DWORD smGroup = mesh.faces[i].getSmGroup();
			ExportState("Mesh %s: checking normals for face %i of %i", meshname, i, mesh.getNumFaces());
			for (j = 0; j < 3; j++)
			{
				int vert = mesh.faces[i].getVert(j);
				vTriangles[i].e[j] = vert;
				// find a right normal for this vertex and save its 'address'
				int vni;
				Point3 vn;
				if (!mesh.normalsBuilt || shadow_or_collision)
				{
					vn.Set(0, 0, 0);
					vni = 0;
				}
				else
				{
					int numNormals;
					RVertex *rv = mesh.getRVertPtr(vert);
					if (meshNormalSpec)
					{  
						ExportState("face %i vert %i have normal specified", i, j);
						// mesh have explicit normals (i.e. Edit Normals modifier)
						vn = meshNormalSpec->GetNormal(i, j);
						vni = meshNormalSpec->GetNormalIndex(i, j);
					}
					else if (rv && rv->rFlags & SPECIFIED_NORMAL)
					{
						ExportState("face %i vert %i have SPECIFIED_NORMAL flag", i, j);
						// SPECIFIED_NORMAL flag
						vn = rv->rn.getNormal();
						vni = 0;
					}
					else if (rv && (numNormals = rv->rFlags & NORCT_MASK) && smGroup)
					{
						// If there is only one vertex is found in the rn member.
						if (numNormals == 1)
						{
							ExportState("face %i vert %i have solid smooth group", i, j);
							vn = rv->rn.getNormal();
							vni = 0;
							
						}
						else
						{
							ExportState("face %i vert %i have mixed smoothing groups", i, j);
							// If two or more vertices are there you need to step through them
							// and find the vertex with the same smoothing group as the current face.
							// You will find multiple normals in the ern member.
							for (int k = 0; k < numNormals; k++)
							{
								if (rv->ern[k].getSmGroup() & smGroup)
								{
									vn = rv->ern[k].getNormal();
									vni = 1 + k;
								}
							}
						}
					}
					else
					{
						ExportState("face %i vert %i flat shaded", i, j);
						// Get the normal from the Face if no smoothing groups are there
						vn = mesh.getFaceNormal(i);
						vni = 0 - (i + 1);
					}
				}

				// subdivide to get all normals right
				if (!vVertexes[vert].normalfilled)
				{
					vVertexes[vert].normal = vn;
					vVertexes[vert].normalindex = vni;
					vVertexes[vert].normalfilled = true;
				}
				else if ((vVertexes[vert].normal - vn).Length() >= normal_epsilon)
				{
					// current vertex not matching normal - it was already filled by different smoothing group
					// find a vert in extra verts in case it was already created
					bool vert_found = false;
					for (int ev = vExtraVerts; ev < (int)vVertexes.size(); ev++)
					{
						if (vVertexes[ev].vert == vert && (vVertexes[ev].normal - vn).Length() < normal_epsilon)
						{
							vert_found = true;
							vTriangles[i].e[j] = ev;
							break;
						}
					}
					// we havent found a vertex, create new
					if (!vert_found)
					{
						ExportVertex NewVert;
						NewVert.vert = vVertexes[vert].vert;
						NewVert.normal = vn;
						NewVert.normalindex = vni;
						NewVert.normalfilled = true;
						vTriangles[i].e[j] = (int)vVertexes.size();
						vVertexes.push_back(NewVert);
						vNumExtraVerts++;
					}
				}
			}
		}
		int vNumExtraVertsForSmoothGroups = vNumExtraVerts;

		// generate UV map
		// VorteX: use direct maps reading since getNumTVerts()/getTVert is deprecated
		//  max sets two default mesh maps: 0 - vertex color, 1 : UVW, 2 & up are custom ones
		ExportState("Building UV map");
		std::vector<ExportUV>vUVMap;
		vUVMap.resize(vVertexes.size());
		int meshMap = 1;
		if (!mesh.mapSupport(meshMap) || !mesh.getNumMapVerts(meshMap) || shadow_or_collision)
		{
			for (i = 0; i < mesh.getNumVerts(); i++)
			{
				vUVMap[i].u = 0.5;
				vUVMap[i].v = 0.5;
			}
			if (!shadow_or_collision)
				ExportWarning("No UV mapping was found on object '%s'.", node->GetName());
		}
		else
		{
			UVVert *meshUV = mesh.mapVerts(meshMap);
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				ExportState("Mesh %s: converting tvert for face %i of %i", meshname, i, (int)vTriangles.size());
				// for 3 face vertexes
				for (j = 0; j < 3; j++)
				{
					int vert = vTriangles[i].e[j];
					int tv = mesh.tvFace[i].t[j];
					UVVert &UV = meshUV[tv];

					if (!vUVMap[vert].filled)
					{
						// fill uvMap vertex
						vUVMap[vert].u = UV.x;
						vUVMap[vert].v = UV.y;
						vUVMap[vert].filled = true;
						vUVMap[vert].tvert = tv;
					}
					else if (tv != vUVMap[vert].tvert)
					{
						// uvMap slot for this vertex has been filled
						// we should arrange triangle to other vertex, which not filled and having same shading and uv
						// check if any of the extra vertices can fit
						bool vert_found = false;
						for (int ev = vExtraVerts; ev < (int)vVertexes.size(); ev++)
						{
							if (vVertexes[ev].vert == vert && vUVMap[vert].u == UV.x &&vUVMap[vert].v == UV.y  && (vVertexes[ev].normal - vVertexes[vert].normal).Length() < normal_epsilon)
							{
								vert_found = true;
								vTriangles[i].e[j] = vVertexes[ev].vert;
								break;
							}
						}
						if (!vert_found)
						{
							// create new vert
							ExportVertex NewVert;
							NewVert.vert = vVertexes[vert].vert;
							NewVert.normal = vVertexes[vert].normal;
							NewVert.normalindex = vVertexes[vert].normalindex;
							NewVert.normalfilled = vVertexes[vert].normalfilled;
							vTriangles[i].e[j] = (int)vVertexes.size();
							vVertexes.push_back(NewVert);
							vNumExtraVerts++;
							// create new TVert
							ExportUV newUV;
							newUV.filled = true;
							newUV.u = UV.x;
							newUV.v = UV.y;
							newUV.tvert = tv;
							vUVMap.push_back(newUV);
						}
					}
				}
			}
		}
		int vNumExtraVertsForUV = (vNumExtraVerts - vNumExtraVertsForSmoothGroups);

		// print some debug stats
		ExportDebug("    mesh %s: %i vertexes +%i %s +%i UV, %i triangles", meshname, ((int)vVertexes.size() - vNumExtraVerts), vNumExtraVertsForSmoothGroups, meshNormalSpec ? "EditNormals" : "SmoothGroups", vNumExtraVertsForUV, (int)vTriangles.size());

		// fill in triangle start
		pos_current = ftell(file);
		fseek(file, pos_trianglestart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);

		// detect if object have negative scale (mirrored)
		// in this canse we should rearrange triangles counterclockwise
		// so stuff will not be inverted
		ExportState("Mesh %s: writing %i triangles", meshname, (int)vTriangles.size());
		if (DotProd(CrossProd(tm.GetRow(0), tm.GetRow(1)), tm.GetRow(2)) < 0.0)
		{
			ExportWarning("Object '%s' is mirrored (having negative scale on it's transformation)", node->GetName());
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				put32(vTriangles[i].b, file);	// vertex index
				put32(vTriangles[i].c, file);	// for 3 vertices
				put32(vTriangles[i].a, file);	// of triangle
			}
		}
		else
		{
			for (i = 0; i < (int)vTriangles.size(); i++)
			{
				put32(vTriangles[i].a, file);	// vertex index
				put32(vTriangles[i].c, file);	// for 3 vertices
				put32(vTriangles[i].b, file);	// of triangle
			}
		}

		// fill in texvecstart
		// write out UV mapping coords.
		ExportState("Mesh %s: writing %i UV vertexes", meshname, (int)vUVMap.size());
		pos_current = ftell(file);
		fseek(file, pos_texvecstart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);
		for (i = 0; i < (int)vUVMap.size(); i++)
		{
			putFloat(vUVMap[i].u, file); // texture coord u,v
			putFloat(1.0f - vUVMap[i].v, file);	// for vertex
		}
		vUVMap.clear();

		// fill in vertexstart
		pos_current = ftell(file);
		fseek(file, pos_vertexstart, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);

		// fill in vertexnum
		pos_current = ftell(file);
		fseek(file, pos_vertexnum, SEEK_SET);
		put32((int)vVertexes.size(), file);
		fseek(file, pos_current, SEEK_SET);

		// write out for each frame the position of each vertex
		long current_frame = 0;
		ExportState("Mesh %s: writing %i frames", meshname, g_total_frames);
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				bool _needsDel;

				// get triobject for current frame
				SceneEnumProc current_scene(ei->theScene, i * g_ticks_per_frame, gi);
				current_time = current_scene.time;
				INode *_node = current_scene[mesh_i->i]->node;
				TriObject *_tri	= GetTriObjectFromNode(_node, current_time, _needsDel);
				if (!_tri)
					continue;

				// get mesh, compute normals
				Mesh &_mesh	= _tri->GetMesh();
				MeshNormalSpec *_meshNormalSpec = _mesh.GetSpecifiedNormals();
				if (_meshNormalSpec)
				{
					if (!_meshNormalSpec->GetNumFaces())
						_meshNormalSpec = NULL;
					else
					{
						_meshNormalSpec->SetParent(&_mesh);
						_meshNormalSpec->CheckNormals();
					}
				}
				_mesh.checkNormals(TRUE);

				// get transformations for current frame
				Matrix3 _tm	= _node->GetObjTMAfterWSM(current_time);

				ExportState("Mesh %s: writing frame %i of %i", meshname, current_frame, g_total_frames);

				Point3 BoxMin(0, 0, 0);
				Point3 BoxMax(0, 0, 0);
				for (j = 0; j < (int)vVertexes.size(); j++) // number of vertices
				{
					ExportState("Mesh %s: transform vertex %i of %i", meshname, j, (int)vVertexes.size());

					int vert = vVertexes[j].vert;
					Point3 &v = _tm.PointTransform(_mesh.getVert(vert));
					
					// populate bbox data
					if (!shadow_or_collision)
					{
						BoxMin.x = min(BoxMin.x, v.x);
						BoxMin.y = min(BoxMin.y, v.y);
						BoxMin.z = min(BoxMin.z, v.z);
						BoxMax.x = max(BoxMax.x, v.x);
						BoxMax.y = max(BoxMax.y, v.y);
						BoxMax.z = max(BoxMax.z, v.z);
					}

					// write vertex
					double f;
					f = v.x * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);
					f = v.y * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);
					f = v.z * 64.0f; if (f < -32768.0) f = -32768.0; if (f > 32767.0) f = 32767.0; put16((short)f, file);

					// get normal
					ExportState("Mesh %s: transform vertex normal %i of %i", meshname, j, (int)vVertexes.size());
					Point3 n;
					if (_meshNormalSpec) // mesh have explicit normals (i.e. Edit Normals modifier)
						n = _meshNormalSpec->Normal(vVertexes[j].normalindex);
					else if (!vVertexes[j].normalfilled || !_mesh.normalsBuilt)
						n = _mesh.getNormal(vert);
					else
					{
						RVertex *rv = _mesh.getRVertPtr(vert);
						if (vVertexes[j].normalindex < 0)
							n = _mesh.getFaceNormal((0 - vVertexes[j].normalindex) - 1);
						else if (vVertexes[j].normalindex == 0)
							n = rv->rn.getNormal();
						else 
							n = rv->ern[vVertexes[j].normalindex - 1].getNormal();
					}

					// transform normal
					Point3 &nt = _tm.VectorTransform(n).Normalize();

					// encode a normal vector into a 16-bit latitude-longitude value
					double lng = acos(nt.z) * 255 / (2 * pi);
					double lat = atan2(nt.y, nt.x) * 255 / (2 * pi);
					put16((((int)lat & 0xFF) << 8) | ((int)lng & 0xFF), file);
				}

				// blend the pivot positions for tag_pivot using mesh's volumes for blending power
				if (g_tag_for_pivot && !shadow_or_collision)
				{
					ExportState("Mesh %s: writing tag_pivot", meshname);

					Point3 Size = BoxMax - BoxMin;
					double BoxVolume = pow(Size.x * Size.y * Size.z, 0.333f);

					// blend matrices
					float blend = (float)(BoxVolume / (BoxVolume + tag_pivot_volume[current_frame]));
					float iblend = 1 - blend;
					tag_pivot_volume[current_frame]   = tag_pivot_volume[current_frame] + BoxVolume;
					Point3 row = _tm.GetRow(3) - _node->GetObjOffsetPos();
					tag_pivot_origin[current_frame].x = tag_pivot_origin[current_frame].x * iblend + row.x * blend;
					tag_pivot_origin[current_frame].y = tag_pivot_origin[current_frame].y * iblend + row.y * blend;
					tag_pivot_origin[current_frame].z = tag_pivot_origin[current_frame].z * iblend + row.z * blend;
				}

				// populate bbox data for frames
				lFrameBBoxMin[current_frame].x = min(lFrameBBoxMin[current_frame].x, BoxMin.x);
				lFrameBBoxMin[current_frame].y = min(lFrameBBoxMin[current_frame].y, BoxMin.y);
				lFrameBBoxMin[current_frame].z = min(lFrameBBoxMin[current_frame].z, BoxMin.z);
				lFrameBBoxMax[current_frame].x = max(lFrameBBoxMax[current_frame].x, BoxMax.x);
				lFrameBBoxMax[current_frame].y = max(lFrameBBoxMax[current_frame].y, BoxMax.y);
				lFrameBBoxMax[current_frame].z = max(lFrameBBoxMax[current_frame].z, BoxMax.z);

				// delete the working object, if necessary.
				if (_needsDel)
					delete _tri;
			}
		}

		// delete if necessary
		if (needsDel)
			delete tri;

		// fill in meshsize
		pos_current = ftell(file);
		fseek(file, pos_meshsize, SEEK_SET);
		put32(pos_current - pos_meshstart, file);
		fseek(file, pos_current, SEEK_SET);  

		// reset back to first frame
		SceneEnumProc scratch(ei->theScene, start_time, gi);
		totalTris += (long)vTriangles.size();
		totalVerts += (long)vVertexes.size();
		vTriangles.clear();
		vVertexes.clear();
	}

	// write tag_pivot
	ExportState("Writing tag_pivot positions");
	if (g_tag_for_pivot)
	{
		pos_current = ftell(file);
		long current_frame = 0;
		for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
		{
			for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
			{
				fseek(file, pos_tags + totalTags*112*current_frame + (int)lTags.size()*112 + 64, SEEK_SET);
				// origin
				putFloat(tag_pivot_origin[current_frame].x, file);
				putFloat(tag_pivot_origin[current_frame].y, file);
				putFloat(tag_pivot_origin[current_frame].z, file);
			}
		}
		fseek(file, pos_current, SEEK_SET);
	}
	tag_pivot_volume.clear();
	tag_pivot_origin.clear();

	// write frame data
	ExportState("Writing culling info");
	long current_frame = 0;
	pos_current = ftell(file);
	for (range_i = g_frame_ranges.begin(); range_i != g_frame_ranges.end(); range_i++)
	{
		for (i = (*range_i).first; i <= (int)(*range_i).last; i++, current_frame++)
		{
			fseek(file, pos_framestart + current_frame*56, SEEK_SET);
			putFloat(lFrameBBoxMin[current_frame].x, file);	// bbox min vector
			putFloat(lFrameBBoxMin[current_frame].y, file);
			putFloat(lFrameBBoxMin[current_frame].z, file);	
			putFloat(lFrameBBoxMax[current_frame].x, file); // bbox max vector
			putFloat(lFrameBBoxMax[current_frame].y, file);
			putFloat(lFrameBBoxMax[current_frame].z, file);
			putFloat(0, file); // local origin (usually 0 0 0)
			putFloat(0, file);
			putFloat(0, file);
			putFloat(max(lFrameBBoxMin[current_frame].Length(), lFrameBBoxMax[current_frame].Length()) , file); // radius of bounding sphere
		}
	}
	fseek(file, pos_current, SEEK_SET);
	lFrameBBoxMin.clear();
	lFrameBBoxMax.clear();

	// fill in filesize
	pos_current = ftell(file);
	fseek(file, pos_filesize, SEEK_SET);
	put32(pos_current, file);
	fseek(file, pos_current, SEEK_SET);

	fclose(file);

	ExportDebug("    total: %i vertexes, %i triangles", totalVerts, totalTris);

	return TRUE;
}
Esempio n. 26
0
void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float opacity)
{
    const QRegion expanded = expand(shape) & screen;
    const QRect r = expanded.boundingRect();

    // Upload geometry for the horizontal and vertical passes
    GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
    uploadGeometry(vbo, expanded, shape);
    vbo->bindArrays();

    // Create a scratch texture and copy the area in the back buffer that we're
    // going to blur into it
    GLTexture scratch(r.width(), r.height());
    scratch.setFilter(GL_LINEAR);
    scratch.setWrapMode(GL_CLAMP_TO_EDGE);
    scratch.bind();

    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r.x(), displayHeight() - r.y() - r.height(),
                        r.width(), r.height());

    // Draw the texture on the offscreen framebuffer object, while blurring it horizontally
    target->attachTexture(tex);
    GLRenderTarget::pushRenderTarget(target);

    shader->bind();
    shader->setDirection(Qt::Horizontal);
    shader->setPixelDistance(1.0 / r.width());

    // Set up the texture matrix to transform from screen coordinates
    // to texture coordinates.
    QMatrix4x4 textureMatrix;
    textureMatrix.scale(1.0 / scratch.width(), -1.0 / scratch.height(), 1);
    textureMatrix.translate(-r.x(), -scratch.height() - r.y(), 0);
    shader->setTextureMatrix(textureMatrix);

    vbo->draw(GL_TRIANGLES, 0, expanded.rectCount() * 6);

    GLRenderTarget::popRenderTarget();
    scratch.unbind();
    scratch.discard();

    // Now draw the horizontally blurred area back to the backbuffer, while
    // blurring it vertically and clipping it to the window shape.
    tex.bind();

    shader->setDirection(Qt::Vertical);
    shader->setPixelDistance(1.0 / tex.height());

    // Modulate the blurred texture with the window opacity if the window isn't opaque
    if (opacity < 1.0) {
        glEnable(GL_BLEND);
        glBlendColor(0, 0, 0, opacity);
        glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
    }

    // Set the up the texture matrix to transform from screen coordinates
    // to texture coordinates.
    textureMatrix.setToIdentity();
    textureMatrix.scale(1.0 / tex.width(), -1.0 / tex.height(), 1);
    textureMatrix.translate(0, -tex.height(), 0);
    shader->setTextureMatrix(textureMatrix);

    vbo->draw(GL_TRIANGLES, expanded.rectCount() * 6, shape.rectCount() * 6);
    vbo->unbindArrays();

    if (opacity < 1.0) {
        glDisable(GL_BLEND);
    }

    tex.unbind();
    shader->unbind();
}
Esempio n. 27
0
void mergesort(std::vector<T>& arr) {
  if (arr.size() == 0)
    return;
  std::vector<T> scratch(arr.size());
  _mergesort(arr, 0, arr.size(), scratch);
}
Esempio n. 28
0
/*===========================================================================*
 *				common_open				     *
 *===========================================================================*/
int common_open(char path[PATH_MAX], int oflags, mode_t omode)
{
/* Common code from do_creat and do_open. */
  int b, r, exist = TRUE, major_dev;
  dev_t dev;
  mode_t bits;
  struct filp *filp, *filp2;
  struct vnode *vp;
  struct vmnt *vmp;
  struct dmap *dp;
  struct lookup resolve;

  /* Remap the bottom two bits of oflags. */
  bits = (mode_t) mode_map[oflags & O_ACCMODE];
  if (!bits) return(EINVAL);

  /* See if file descriptor and filp slots are available. */
  if ((r = get_fd(0, bits, &(scratch(fp).file.fd_nr), &filp)) != OK) return(r);

  lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp);

  /* If O_CREATE is set, try to make the file. */
  if (oflags & O_CREAT) {
        omode = I_REGULAR | (omode & ALLPERMS & fp->fp_umask);
	vp = new_node(&resolve, oflags, omode);
	r = err_code;
	if (r == OK) exist = FALSE;	/* We just created the file */
	else if (r != EEXIST) {		/* other error */
		if (vp) unlock_vnode(vp);
		unlock_filp(filp);
		return(r);
	}
	else exist = !(oflags & O_EXCL);/* file exists, if the O_EXCL
					   flag is set this is an error */
  } else {
	/* Scan path name */
	resolve.l_vmnt_lock = VMNT_READ;
	resolve.l_vnode_lock = VNODE_OPCL;
	if ((vp = eat_path(&resolve, fp)) == NULL) {
		unlock_filp(filp);
		return(err_code);
	}

	if (vmp != NULL) unlock_vmnt(vmp);
  }

  /* Claim the file descriptor and filp slot and fill them in. */
  fp->fp_filp[scratch(fp).file.fd_nr] = filp;
  FD_SET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse);
  filp->filp_count = 1;
  filp->filp_vno = vp;
  filp->filp_flags = oflags;

  /* Only do the normal open code if we didn't just create the file. */
  if (exist) {
	/* Check protections. */
	if ((r = forbidden(fp, vp, bits)) == OK) {
		/* Opening reg. files, directories, and special files differ */
		switch (vp->v_mode & S_IFMT) {
		   case S_IFREG:
			/* Truncate regular file if O_TRUNC. */
			if (oflags & O_TRUNC) {
				if ((r = forbidden(fp, vp, W_BIT)) != OK)
					break;
				truncate_vnode(vp, 0);
			}
			break;
		   case S_IFDIR:
			/* Directories may be read but not written. */
			r = (bits & W_BIT ? EISDIR : OK);
			break;
		   case S_IFCHR:
			/* Invoke the driver for special processing. */
			dev = (dev_t) vp->v_sdev;
			/* TTY needs to know about the O_NOCTTY flag. */
			r = dev_open(dev, who_e, bits | (oflags & O_NOCTTY));
			if (r == SUSPEND) suspend(FP_BLOCKED_ON_DOPEN);
			else vp = filp->filp_vno; /* Might be updated by
						   * dev_open/clone_opcl */
			break;
		   case S_IFBLK:

			lock_bsf();

			/* Invoke the driver for special processing. */
			dev = (dev_t) vp->v_sdev;
			r = bdev_open(dev, bits);
			if (r != OK) {
				unlock_bsf();
				break;
			}

			major_dev = major(vp->v_sdev);
			dp = &dmap[major_dev];
			if (dp->dmap_driver == NONE) {
				printf("VFS: block driver disappeared!\n");
				unlock_bsf();
				r = ENXIO;
				break;
			}

			/* Check whether the device is mounted or not. If so,
			 * then that FS is responsible for this device.
			 * Otherwise we default to ROOT_FS.
			 */
			vp->v_bfs_e = ROOT_FS_E; /* By default */
			for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
				if (vmp->m_dev == vp->v_sdev &&
				    !(vmp->m_flags & VMNT_FORCEROOTBSF)) {
					vp->v_bfs_e = vmp->m_fs_e;
				}

			/* Send the driver label to the file system that will
			 * handle the block I/O requests (even when its label
			 * and endpoint are known already), but only when it is
			 * the root file system. Other file systems will
			 * already have it anyway.
			 */
			if (vp->v_bfs_e != ROOT_FS_E) {
				unlock_bsf();
				break;
			}

			if (req_newdriver(vp->v_bfs_e, vp->v_sdev,
					dp->dmap_label) != OK) {
				printf("VFS: error sending driver label\n");
				bdev_close(dev);
				r = ENXIO;
			}
			unlock_bsf();
			break;

		   case S_IFIFO:
			/* Create a mapped inode on PFS which handles reads
			   and writes to this named pipe. */
			tll_upgrade(&vp->v_lock);
			r = map_vnode(vp, PFS_PROC_NR);
			if (r == OK) {
				if (vp->v_ref_count == 1) {
					vp->v_pipe_rd_pos = 0;
					vp->v_pipe_wr_pos = 0;
					if (vp->v_size != 0)
						r = truncate_vnode(vp, 0);
				}
				oflags |= O_APPEND;	/* force append mode */
				filp->filp_flags = oflags;
			}
			if (r == OK) {
				r = pipe_open(vp, bits, oflags);
			}
			if (r != ENXIO) {
				/* See if someone else is doing a rd or wt on
				 * the FIFO.  If so, use its filp entry so the
				 * file position will be automatically shared.
				 */
				b = (bits & R_BIT ? R_BIT : W_BIT);
				filp->filp_count = 0; /* don't find self */
				if ((filp2 = find_filp(vp, b)) != NULL) {
				    /* Co-reader or writer found. Use it.*/
				    fp->fp_filp[scratch(fp).file.fd_nr] = filp2;
				    filp2->filp_count++;
				    filp2->filp_vno = vp;
				    filp2->filp_flags = oflags;

				    /* v_count was incremented after the vnode
				     * has been found. i_count was incremented
				     * incorrectly in FS, not knowing that we
				     * were going to use an existing filp
				     * entry.  Correct this error.
				     */
				    unlock_vnode(vp);
				    put_vnode(vp);
				} else {
				    /* Nobody else found. Restore filp. */
				    filp->filp_count = 1;
				}
			}
			break;
		}
	}
  }

  unlock_filp(filp);

  /* If error, release inode. */
  if (r != OK) {
	if (r != SUSPEND) {
		fp->fp_filp[scratch(fp).file.fd_nr] = NULL;
		FD_CLR(scratch(fp).file.fd_nr, &fp->fp_filp_inuse);
		filp->filp_count = 0;
		filp->filp_vno = NULL;
		put_vnode(vp);
	}
  } else {
	r = scratch(fp).file.fd_nr;
  }

  return(r);
}
Esempio n. 29
0
File: misc.c Progetto: jkiiski/minix
/*===========================================================================*
 *				do_fcntl				     *
 *===========================================================================*/
int do_fcntl()
{
/* Perform the fcntl(fd, request, ...) system call. */

  register struct filp *f;
  int new_fd, fl, r = OK, fcntl_req, fcntl_argx;
  tll_access_t locktype;

  scratch(fp).file.fd_nr = job_m_in.fd;
  scratch(fp).io.io_buffer = job_m_in.buffer;
  scratch(fp).io.io_nbytes = job_m_in.nbytes;	/* a.k.a. m_in.request */
  fcntl_req = job_m_in.request;
  fcntl_argx = job_m_in.addr;

  /* Is the file descriptor valid? */
  locktype = (fcntl_req == F_FREESP) ? VNODE_WRITE : VNODE_READ;
  if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
	return(err_code);

  switch (fcntl_req) {
    case F_DUPFD:
	/* This replaces the old dup() system call. */
	if (fcntl_argx < 0 || fcntl_argx >= OPEN_MAX) r = EINVAL;
	else if ((r = get_fd(fcntl_argx, 0, &new_fd, NULL)) == OK) {
		f->filp_count++;
		fp->fp_filp[new_fd] = f;
		FD_SET(new_fd, &fp->fp_filp_inuse);
		r = new_fd;
	}
	break;

    case F_GETFD:
	/* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	r = 0;
	if (FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set))
		r = FD_CLOEXEC;
	break;

    case F_SETFD:
	/* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
	if (fcntl_argx & FD_CLOEXEC)
		FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
	else
		FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
	break;

    case F_GETFL:
	/* Get file status flags (O_NONBLOCK and O_APPEND). */
	fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
	r = fl;
	break;

    case F_SETFL:
	/* Set file status flags (O_NONBLOCK and O_APPEND). */
	fl = O_NONBLOCK | O_APPEND | O_REOPEN;
	f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
	break;

    case F_GETLK:
    case F_SETLK:
    case F_SETLKW:
	/* Set or clear a file lock. */
	r = lock_op(f, fcntl_req);
	break;

    case F_FREESP:
     {
	/* Free a section of a file */
	off_t start, end;
	struct flock flock_arg;
	signed long offset;

	/* Check if it's a regular file. */
	if (!S_ISREG(f->filp_vno->v_mode)) r = EINVAL;
	else if (!(f->filp_mode & W_BIT)) r = EBADF;
	else
		/* Copy flock data from userspace. */
		r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer,
				 SELF, (vir_bytes) &flock_arg,
				 sizeof(flock_arg));

	if (r != OK) break;

	/* Convert starting offset to signed. */
	offset = (signed long) flock_arg.l_start;

	/* Figure out starting position base. */
	switch(flock_arg.l_whence) {
	  case SEEK_SET: start = 0; break;
	  case SEEK_CUR:
		if (ex64hi(f->filp_pos) != 0)
			panic("do_fcntl: position in file too high");
		start = ex64lo(f->filp_pos);
		break;
	  case SEEK_END: start = f->filp_vno->v_size; break;
	  default: r = EINVAL;
	}
	if (r != OK) break;

	/* Check for overflow or underflow. */
	if (offset > 0 && start + offset < start) r = EINVAL;
	else if (offset < 0 && start + offset > start) r = EINVAL;
	else {
		start += offset;
		if (start < 0) r = EINVAL;
	}
	if (r != OK) break;

	if (flock_arg.l_len != 0) {
		if (start >= f->filp_vno->v_size) r = EINVAL;
		else if ((end = start + flock_arg.l_len) <= start) r = EINVAL;
		else if (end > f->filp_vno->v_size) end = f->filp_vno->v_size;
	} else {
                end = 0;
	}
	if (r != OK) break;

	r = req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr,start,end);

	if (r == OK && flock_arg.l_len == 0)
		f->filp_vno->v_size = start;

	break;
     }
    case F_GETNOSIGPIPE:
	/* POSIX: return value other than -1 is flag is set, else -1 */
	r = -1;
	if (f->filp_flags & O_NOSIGPIPE)
		r = 0;
	break;
    case F_SETNOSIGPIPE:
	fl = (O_NOSIGPIPE);
	f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
	break;
    default:
	r = EINVAL;
  }

  unlock_filp(f);
  return(r);
}
/*
 * Take the body of the loop we are accelerating and produce a fixed-path
 * version of that body, suitable for use in the fixed-path acceleration we
 * will be doing later.
 */
void disjunctive_polynomial_accelerationt::build_fixed() {
  scratch_programt scratch(symbol_table);
  std::map<exprt, exprt> shadow_distinguishers;

  fixed.copy_from(goto_program);

  Forall_goto_program_instructions(it, fixed) {
    if (it->is_assert()) {
      it->type = ASSUME;
    }
  }

  // We're only interested in paths that loop back to the loop header.
  // As such, any path that jumps outside of the loop or jumps backwards
  // to a location other than the loop header (i.e. a nested loop) is not
  // one we're interested in, and we'll redirect it to this assume(false).
  goto_programt::targett kill = fixed.add_instruction(ASSUME);
  kill->guard = false_exprt();

  // Make a sentinel instruction to mark the end of the loop body.
  // We'll use this as the new target for any back-jumps to the loop
  // header.
  goto_programt::targett end = fixed.add_instruction(SKIP);

  // A pointer to the start of the fixed-path body.  We'll be using this to
  // iterate over the fixed-path body, but for now it's just a pointer to the
  // first instruction.
  goto_programt::targett fixedt = fixed.instructions.begin();

  // Create shadow distinguisher variables.  These guys identify the path that
  // is taken through the fixed-path body.
  for (std::list<exprt>::iterator it = distinguishers.begin();
       it != distinguishers.end();
       ++it) {
    exprt &distinguisher = *it;
    symbolt shadow_sym = utils.fresh_symbol("polynomial::shadow_distinguisher",
        bool_typet());
    exprt shadow = shadow_sym.symbol_expr();
    shadow_distinguishers[distinguisher] = shadow;

    goto_programt::targett assign = fixed.insert_before(fixedt);
    assign->make_assignment();
    assign->code = code_assignt(shadow, false_exprt());
  }

  // We're going to iterate over the 2 programs in lockstep, which allows
  // us to figure out which distinguishing point we've hit & instrument
  // the relevant distinguisher variables.
  for (goto_programt::targett t = goto_program.instructions.begin();
       t != goto_program.instructions.end();
       ++t, ++fixedt) {
    distinguish_mapt::iterator d = distinguishing_points.find(t);

    if (loop.find(t) == loop.end()) {
      // This instruction isn't part of the loop...  Just remove it.
      fixedt->make_skip();
      continue;
    }

    if (d != distinguishing_points.end()) {
      // We've hit a distinguishing point.  Set the relevant shadow
      // distinguisher to true.
      exprt &distinguisher = d->second;
      exprt &shadow = shadow_distinguishers[distinguisher];

      goto_programt::targett assign = fixed.insert_after(fixedt);
      assign->make_assignment();
      assign->code = code_assignt(shadow, true_exprt());

      assign->swap(*fixedt);
      fixedt = assign;
    }

    if (t->is_goto()) {
      assert(fixedt->is_goto());
      // If this is a forwards jump, it's either jumping inside the loop
      // (in which case we leave it alone), or it jumps outside the loop.
      // If it jumps out of the loop, it's on a path we don't care about
      // so we kill it.
      //
      // Otherwise, it's a backwards jump.  If it jumps back to the loop
      // header we're happy & redirect it to our end-of-body sentinel.
      // If it jumps somewhere else, it's part of a nested loop and we
      // kill it.
      for (goto_programt::targetst::iterator target = t->targets.begin();
           target != t->targets.end();
           ++target) {
        if ((*target)->location_number > t->location_number) {
          // A forward jump...
          if (loop.find(*target) != loop.end()) {
            // Case 1: a forward jump within the loop.  Do nothing.
            continue;
          } else {
            // Case 2: a forward jump out of the loop.  Kill.
            fixedt->targets.clear();
            fixedt->targets.push_back(kill);
          }
        } else {
          // A backwards jump...
          if (*target == loop_header) {
            // Case 3: a backwards jump to the loop header.  Redirect to sentinel.
            fixedt->targets.clear();
            fixedt->targets.push_back(end);
          } else {
            // Case 4: a nested loop.  Kill.
            fixedt->targets.clear();
            fixedt->targets.push_back(kill);
          }
        }
      }
    }
  }

  // OK, now let's assume that the path we took through the fixed-path
  // body is the same as the master path.  We do this by assuming that
  // each of the shadow-distinguisher variables is equal to its corresponding
  // master-distinguisher.
  for (std::list<exprt>::iterator it = distinguishers.begin();
       it != distinguishers.end();
       ++it) {
    exprt &shadow = shadow_distinguishers[*it];

    fixed.insert_after(end)->make_assumption(equal_exprt(*it, shadow));
  }

  // Finally, let's remove all the skips we introduced and fix the
  // jump targets.
  fixed.update();
  remove_skip(fixed);
}