void attach( const ValueType * const arg_ptr, AllocationTracker const & tracker ) { typedef char const * const byte; m_alloc_ptr = reinterpret_cast<ValueType *>(tracker.alloc_ptr()); size_t byte_offset = reinterpret_cast<byte>(arg_ptr) - reinterpret_cast<byte>(m_alloc_ptr); const bool ok_aligned = 0 == byte_offset % sizeof(ValueType); const size_t count = tracker.alloc_size() / sizeof(ValueType); const bool ok_contains = (m_alloc_ptr <= arg_ptr) && (arg_ptr < (m_alloc_ptr + count)); if (ok_aligned && ok_contains) { if (tracker.attribute() == NULL ) { MemorySpace::texture_object_attach( tracker , sizeof(ValueType) , cudaCreateChannelDesc< AliasType >() ); } m_obj = dynamic_cast<TextureAttribute*>(tracker.attribute())->m_tex_obj; m_offset = arg_ptr - m_alloc_ptr; } else if( !ok_contains ) { throw_runtime_exception("Error: cannot attach a texture object to a tracker which does not bound the pointer."); } else { throw_runtime_exception("Error: cannot attach a texture object to an incorrectly aligned pointer."); } }
void * PageAlignedAllocator::reallocate(void * old_ptr, size_t old_size, size_t new_size) { void * ptr = NULL; #if defined( NO_MMAP ) || defined( __APPLE__ ) || defined( __CYGWIN__ ) if (old_size != new_size) { ptr = allocate( new_size ); memcpy(ptr, old_ptr, (old_size < new_size ? old_size : new_size) ); deallocate( old_ptr, old_size ); } else { ptr = old_ptr; } #else ptr = mremap( old_ptr, old_size, new_size, MREMAP_MAYMOVE ); if (ptr == MAP_FAILED) { throw_runtime_exception("Error: Page Aligned Allocator could not reallocate memory"); } #endif return ptr; }
void* PageAlignedAllocator::allocate( size_t size ) { void *ptr = NULL; if (size) { #if !defined NO_MMAP if ( size < MMAP_USE_HUGE_PAGES ) { ptr = mmap( NULL, size, MMAP_PROTECTION, MMAP_FLAGS, -1 /*file descriptor*/, 0 /*offset*/); } else { ptr = mmap( NULL, size, MMAP_PROTECTION, MMAP_FLAGS_HUGE, -1 /*file descriptor*/, 0 /*offset*/); } if (ptr == MAP_FAILED) { ptr = NULL; } #else static const size_t page_size = 4096; // TODO: read in from sysconf( _SC_PAGE_SIZE ) ptr = raw_aligned_allocate( size, page_size); #endif if (!ptr) { std::ostringstream msg ; msg << name() << ": allocate(" << size << ") FAILED"; throw_runtime_exception( msg.str() ); } } return ptr; }
// Iterate records to print orphaned memory ... void SharedAllocationRecord< Kokkos::HostSpace , void >:: print_records( std::ostream & s , const Kokkos::HostSpace & , bool detail ) { #ifdef KOKKOS_DEBUG SharedAllocationRecord< void , void >::print_host_accessible_records( s , "HostSpace" , & s_root_record , detail ); #else throw_runtime_exception("SharedAllocationRecord<HostSpace>::print_records only works with KOKKOS_DEBUG enabled"); #endif }
void * MallocAllocator::reallocate(void * old_ptr, size_t /*old_size*/, size_t new_size) { void * ptr = realloc(old_ptr, new_size); if (new_size > 0u && ptr == NULL) { throw_runtime_exception("Error: Malloc Allocator could not reallocate memory"); } return ptr; }
void assert_counts_are_equal_throw( const unsigned x_count , const unsigned y_count ) { std::ostringstream msg ; msg << "Kokkos::Impl::assert_counts_are_equal_throw( " << x_count << " != " << y_count << " )" ; throw_runtime_exception( msg.str() ); }
/* * Class: mapnik_FeatureSet * Method: getId * Signature: ()I */ JNIEXPORT jint JNICALL Java_mapnik_FeatureSet_getId (JNIEnv *env, jobject fsobj) { PREAMBLE; mapnik::feature_ptr* fp=LOAD_FEATURE_POINTER(fsobj); if (!fp) { throw_runtime_exception(env, "No feature loaded"); return 0; } return (*fp)->id(); TRAILER(0); }
/* * Class: mapnik_FeatureSet * Method: getEnvelope * Signature: ()Lmapnik/Box2d; */ JNIEXPORT jobject JNICALL Java_mapnik_FeatureSet_getEnvelope (JNIEnv *env, jobject fsobj) { PREAMBLE; mapnik::feature_ptr* fp=LOAD_FEATURE_POINTER(fsobj); if (!fp) { throw_runtime_exception(env, "No feature loaded"); return 0; } return box2dFromNative(env, (*fp)->envelope()); TRAILER(0); }
/* * Class: mapnik_Image * Method: alloc * Signature: (Lmapnik/Image;)J */ JNIEXPORT jlong JNICALL Java_mapnik_Image_alloc__Lmapnik_Image_2 (JNIEnv *env, jclass c, jobject iobjother) { PREAMBLE; if (!iobjother) { throw_runtime_exception(env, "Image cannot be null in call to constructor"); return 0; } mapnik::image_32* other=LOAD_IMAGE_POINTER(iobjother); mapnik::image_32* im=new mapnik::image_32(*other); return FROM_POINTER(im); TRAILER(0); }
/* * Class: mapnik_MapDefinition * Method: saveMap * Signature: (Ljava/lang/String;Z)V */ JNIEXPORT void JNICALL Java_mapnik_MapDefinition_saveMap (JNIEnv *env, jobject mapobject, jstring filenamej, jboolean explicitDefaults) { PREAMBLE; mapnik::Map* map=LOAD_MAP_POINTER(mapobject); if (!filenamej) { throw_runtime_exception(env, "Filename is required"); return; } refjavastring filename(env, filenamej); mapnik::save_map(*map, filename.stringz, explicitDefaults); TRAILER_VOID; }
void* MallocAllocator::allocate( size_t size ) { void * ptr = NULL; if (size) { ptr = malloc(size); if (!ptr) { std::ostringstream msg ; msg << name() << ": allocate(" << size << ") FAILED"; throw_runtime_exception( msg.str() ); } } return ptr; }
void* AlignedAllocator::allocate( size_t size ) { void * ptr = 0 ; if ( size ) { ptr = raw_aligned_allocate(size, MEMORY_ALIGNMENT); if (!ptr) { std::ostringstream msg ; msg << name() << ": allocate(" << size << ") FAILED"; throw_runtime_exception( msg.str() ); } } return ptr; }
/* * Class: mapnik_FeatureSet * Method: getProperty * Signature: (Ljava/lang/String;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_mapnik_FeatureSet_getProperty (JNIEnv *env, jobject fsobj, jstring namej) { PREAMBLE; mapnik::feature_ptr* fp=LOAD_FEATURE_POINTER(fsobj); if (!fp) { throw_runtime_exception(env, "No feature loaded"); return 0; } refjavastring name(env,namej); // Convert the value mapnik::value_type const& value= (*fp)->get(name.stringz); return mapnik::value_type::visit(value, value_to_java(env)); TRAILER(0); }
/* * Class: mapnik_Renderer * Method: renderAgg * Signature: (Lmapnik/MapDefinition;Lmapnik/Image;DII)V */ JNIEXPORT void JNICALL Java_mapnik_Renderer_renderAgg (JNIEnv *env, jclass c, jobject mapobj, jobject imobj, jdouble scale_factor, jint offset_x, jint offset_y) { PREAMBLE; if (!mapobj || !imobj || offset_x<0 || offset_y<0) { throw_runtime_exception(env, "Illegal arguments in call"); return; } mapnik::Map* map=LOAD_MAP_POINTER(mapobj); mapnik::image_32* im=LOAD_IMAGE_POINTER(imobj); mapnik::agg_renderer<mapnik::image_32> ren(*map, *im, scale_factor, offset_x, offset_y); ren.apply(); TRAILER_VOID; }
void assert_shapes_are_equal_throw( const unsigned x_scalar_size , const unsigned x_rank , const size_t x_N0 , const unsigned x_N1 , const unsigned x_N2 , const unsigned x_N3 , const unsigned x_N4 , const unsigned x_N5 , const unsigned x_N6 , const unsigned x_N7 , const unsigned y_scalar_size , const unsigned y_rank , const size_t y_N0 , const unsigned y_N1 , const unsigned y_N2 , const unsigned y_N3 , const unsigned y_N4 , const unsigned y_N5 , const unsigned y_N6 , const unsigned y_N7 ) { std::ostringstream msg ; msg << "Kokkos::Impl::assert_shape_are_equal_throw( {" << " scalar_size(" << x_scalar_size << ") rank(" << x_rank << ") dimension(" ; if ( 0 < x_rank ) { msg << " " << x_N0 ; } if ( 1 < x_rank ) { msg << " " << x_N1 ; } if ( 2 < x_rank ) { msg << " " << x_N2 ; } if ( 3 < x_rank ) { msg << " " << x_N3 ; } if ( 4 < x_rank ) { msg << " " << x_N4 ; } if ( 5 < x_rank ) { msg << " " << x_N5 ; } if ( 6 < x_rank ) { msg << " " << x_N6 ; } if ( 7 < x_rank ) { msg << " " << x_N7 ; } msg << " ) } != { " << " scalar_size(" << y_scalar_size << ") rank(" << y_rank << ") dimension(" ; if ( 0 < y_rank ) { msg << " " << y_N0 ; } if ( 1 < y_rank ) { msg << " " << y_N1 ; } if ( 2 < y_rank ) { msg << " " << y_N2 ; } if ( 3 < y_rank ) { msg << " " << y_N3 ; } if ( 4 < y_rank ) { msg << " " << y_N4 ; } if ( 5 < y_rank ) { msg << " " << y_N5 ; } if ( 6 < y_rank ) { msg << " " << y_N6 ; } if ( 7 < y_rank ) { msg << " " << y_N7 ; } msg << " ) } )" ; throw_runtime_exception( msg.str() ); }
/* * Class: mapnik_FeatureSet * Method: getProperty * Signature: (Ljava/lang/String;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_mapnik_FeatureSet_getProperty (JNIEnv *env, jobject fsobj, jstring namej) { PREAMBLE; mapnik::feature_ptr* fp=LOAD_FEATURE_POINTER(fsobj); if (!fp) { throw_runtime_exception(env, "No feature loaded"); return 0; } refjavastring name(env,namej); std::map<std::string,mapnik::value>::iterator iter=(*fp)->props().find(name.stringz); if (iter==(*fp)->end()) return 0; // Convert the value mapnik::value_base const& value=iter->second.base(); return boost::apply_visitor(value_to_java(env), value); TRAILER(0); }
/* * Class: mapnik_FeatureSet * Method: getPropertyNames * Signature: ()Ljava/util/Set; */ JNIEXPORT jobject JNICALL Java_mapnik_FeatureSet_getPropertyNames (JNIEnv *env, jobject fsobj) { PREAMBLE; mapnik::feature_ptr* fp=LOAD_FEATURE_POINTER(fsobj); if (!fp) { throw_runtime_exception(env, "No feature loaded"); return 0; } jobject ret=env->NewObject(CLASS_HASHSET, CTOR_HASHSET); for (std::map<std::string,mapnik::value>::iterator iter=(*fp)->begin(); iter!=(*fp)->end(); iter++) { std::string const& name(iter->first); env->CallBooleanMethod(ret, METHOD_HASHSET_ADD, env->NewStringUTF(name.c_str())); } return ret; TRAILER(0); }
/* * Class: mapnik_FeatureSet * Method: _loadGeometries * Signature: ()[Lmapnik/Geometry; */ JNIEXPORT jobjectArray JNICALL Java_mapnik_FeatureSet__1loadGeometries (JNIEnv *env, jobject fsobj) { PREAMBLE; mapnik::feature_ptr* fp=LOAD_FEATURE_POINTER(fsobj); if (!fp) { throw_runtime_exception(env, "No feature loaded"); return 0; } unsigned count=(*fp)->num_geometries(); jobjectArray ret=env->NewObjectArray(count, CLASS_GEOMETRY, (jobject)0); for (unsigned index=0; index<count; index++) { mapnik::geometry_type &g((*fp)->get_geometry(index)); jobject gobject=env->NewObject(CLASS_GEOMETRY, CTOR_NATIVEOBJECT); env->SetLongField(gobject, FIELD_PTR, FROM_POINTER(&g)); env->SetObjectArrayElement(ret, index, gobject); } return ret; TRAILER(0); }
KOKKOS_INLINE_FUNCTION explicit CudaTextureFetch( const ValueType * const arg_ptr, AllocationTracker const & tracker ) : m_obj( 0 ) , m_alloc_ptr(0) , m_offset(0) { #if defined( KOKKOS_USE_LDG_INTRINSIC ) m_alloc_ptr(arg_ptr); #elif defined( __CUDACC__ ) && ! defined( __CUDA_ARCH__ ) if ( arg_ptr != NULL ) { if ( tracker.is_valid() ) { attach( arg_ptr, tracker ); } else { AllocationTracker found_tracker = AllocationTracker::find<typename MemorySpace::allocator>(arg_ptr); if ( found_tracker.is_valid() ) { attach( arg_ptr, found_tracker ); } else { throw_runtime_exception("Error: cannot attach a texture object to an untracked pointer!"); } } } #endif }
void assert_shape_effective_rank1_at_leastN_throw( const size_t x_rank , const size_t x_N0 , const size_t x_N1 , const size_t x_N2 , const size_t x_N3 , const size_t x_N4 , const size_t x_N5 , const size_t x_N6 , const size_t x_N7 , const size_t N0 ) { std::ostringstream msg ; msg << "Kokkos::Impl::assert_shape_effective_rank1_at_leastN_throw( shape = {" ; if ( 0 < x_rank ) { msg << " " << x_N0 ; } if ( 1 < x_rank ) { msg << " " << x_N1 ; } if ( 2 < x_rank ) { msg << " " << x_N2 ; } if ( 3 < x_rank ) { msg << " " << x_N3 ; } if ( 4 < x_rank ) { msg << " " << x_N4 ; } if ( 5 < x_rank ) { msg << " " << x_N5 ; } if ( 6 < x_rank ) { msg << " " << x_N6 ; } if ( 7 < x_rank ) { msg << " " << x_N7 ; } msg << " } N = " << N0 << " )" ; throw_runtime_exception( msg.str() ); }
void AssertShapeBoundsAbort< Kokkos::HostSpace >::apply( const size_t rank , const size_t n0 , const size_t n1 , const size_t n2 , const size_t n3 , const size_t n4 , const size_t n5 , const size_t n6 , const size_t n7 , const size_t arg_rank , const size_t i0 , const size_t i1 , const size_t i2 , const size_t i3 , const size_t i4 , const size_t i5 , const size_t i6 , const size_t i7 ) { std::ostringstream msg ; msg << "Kokkos::Impl::AssertShapeBoundsAbort( shape = {" ; if ( 0 < rank ) { msg << " " << n0 ; } if ( 1 < rank ) { msg << " " << n1 ; } if ( 2 < rank ) { msg << " " << n2 ; } if ( 3 < rank ) { msg << " " << n3 ; } if ( 4 < rank ) { msg << " " << n4 ; } if ( 5 < rank ) { msg << " " << n5 ; } if ( 6 < rank ) { msg << " " << n6 ; } if ( 7 < rank ) { msg << " " << n7 ; } msg << " } index = {" ; if ( 0 < arg_rank ) { msg << " " << i0 ; } if ( 1 < arg_rank ) { msg << " " << i1 ; } if ( 2 < arg_rank ) { msg << " " << i2 ; } if ( 3 < arg_rank ) { msg << " " << i3 ; } if ( 4 < arg_rank ) { msg << " " << i4 ; } if ( 5 < arg_rank ) { msg << " " << i5 ; } if ( 6 < arg_rank ) { msg << " " << i6 ; } if ( 7 < arg_rank ) { msg << " " << i7 ; } msg << " } )" ; throw_runtime_exception( msg.str() ); }
/* * Class: mapnik_FeatureSet * Method: _loadGeometries * Signature: ()[Lmapnik/Geometry; */ JNIEXPORT jobjectArray JNICALL Java_mapnik_FeatureSet__1loadGeometries (JNIEnv *env, jobject fsobj) { PREAMBLE; mapnik::feature_ptr* fp=LOAD_FEATURE_POINTER(fsobj); if (!fp) { throw_runtime_exception(env, "No feature loaded"); return 0; } // Mapnik 3.x only holds one geometry<> per feature_impl. // (In Mapnik 2.x this used to be a variable-length vector of geometries.) unsigned count=1; jobjectArray ret=env->NewObjectArray(count, CLASS_GEOMETRY, (jobject)0); for (unsigned index=0; index<count; index++) { mapnik::geometry::geometry<double> const &g((*fp)->get_geometry()); jobject gobject=env->NewObject(CLASS_GEOMETRY, CTOR_NATIVEOBJECT); env->SetLongField(gobject, FIELD_PTR, FROM_POINTER(&g)); env->SetObjectArrayElement(ret, index, gobject); } return ret; TRAILER(0); }
/** * @brief Main function for oaextendmpi and oaextendsingle * @param argc * @param argv[] * @return */ int main (int argc, char *argv[]) { #ifdef OAEXTEND_SINGLECORE const int n_processors = 1; const int this_rank = 0; #else MPI::Init (argc, argv); const int n_processors = MPI::COMM_WORLD.Get_size (); const int this_rank = MPI::COMM_WORLD.Get_rank (); #endif // printf("MPI: this_rank %d\n", this_rank); /*----------SET STARTING ARRAY(S)-----------*/ if (this_rank != MASTER) { #ifdef OAEXTEND_MULTICORE slave_print (QUIET, "M: running core %d/%d\n", this_rank, n_processors); #endif algorithm_t algorithm = MODE_INVALID; AnyOption *opt = parseOptions (argc, argv, algorithm); OAextend oaextend; oaextend.setAlgorithm (algorithm); #ifdef OAEXTEND_MULTICORE log_print (NORMAL, "slave: receiving algorithm int\n"); algorithm = (algorithm_t)receive_int_slave (); oaextend.setAlgorithm (algorithm); // printf("slave %d: receive algorithm %d\n", this_rank, algorithm); #endif extend_slave_code (this_rank, oaextend); delete opt; } else { double Tstart = get_time_ms (); int nr_extensions; arraylist_t solutions, extensions; algorithm_t algorithm = MODE_INVALID; AnyOption *opt = parseOptions (argc, argv, algorithm); print_copyright (); int loglevel = opt->getIntValue ('l', NORMAL); setloglevel (loglevel); int dosort = opt->getIntValue ('s', 1); int userowsymm = opt->getIntValue ("rowsymmetry", 1); int maxk = opt->getIntValue ("maxk", 100000); int initcolprev = opt->getIntValue ("initcolprev", 1); const bool streaming = opt->getFlag ("streaming"); bool restart = false; if (opt->getValue ("restart") != NULL || opt->getValue ('r') != NULL) { restart = true; } const char *oaconfigfile = opt->getStringValue ('c', "oaconfig.txt"); const char *resultprefix = opt->getStringValue ('o', "result"); arrayfile::arrayfilemode_t mode = arrayfile_t::parseModeString (opt->getStringValue ('f', "T")); OAextend oaextend; oaextend.setAlgorithm (algorithm); if (streaming) { logstream (SYSTEM) << "operating in streaming mode, sorting of arrays will not work " << std::endl; oaextend.extendarraymode = OAextend::STOREARRAY; } // J5_45 int xx = opt->getFlag ('x'); if (xx) { oaextend.j5structure = J5_45; } if (userowsymm == 0) { oaextend.use_row_symmetry = userowsymm; printf ("use row symmetry -> %d\n", oaextend.use_row_symmetry); } if (opt->getFlag ('g')) { std::cout << "only generating arrays (no LMC check)" << endl; oaextend.checkarrays = 0; } if (opt->getFlag ("help") || (opt->getValue ("coptions") != NULL)) { if (opt->getFlag ("help")) { opt->printUsage (); } if (opt->getValue ("coptions") != NULL) { print_options (cout); } } else { logstream (QUIET) << "#time start: " << currenttime () << std::endl; arraydata_t *ad; ad = readConfigFile (oaconfigfile); ad->lmc_overflow_check (); if (ad == 0) { return 1; } log_print (NORMAL, "Using design file: %s (runs %d, strength %d)\n", oaconfigfile, ad->N, ad->strength); if (oaextend.getAlgorithm () == MODE_AUTOSELECT) { oaextend.setAlgorithmAuto (ad); } #ifdef OAEXTEND_SINGLECORE if (initcolprev == 0) { log_print (NORMAL, "setting oaextend.init_column_previous to %d\n", INITCOLUMN_ZERO); oaextend.init_column_previous = INITCOLUMN_ZERO; } #endif #ifdef OAEXTEND_MULTICORE int alg = oaextend.getAlgorithm (); for (int i = 0; i < n_processors; i++) { if (i == MASTER) { continue; } log_print (NORMAL, "MASTER: sending algorithm %d to slave %d\n", alg, i); send_int (alg, i); } #endif colindex_t col_start; log_print (SYSTEM, "using algorithm %d (%s)\n", oaextend.getAlgorithm (), oaextend.getAlgorithmName ().c_str ()); if (log_print (NORMAL, "")) { cout << oaextend.__repr__ (); } if (restart) { // start from result file int initres = init_restart (opt->getValue ('r'), col_start, solutions); if (initres == 1) { // check if restarting went OK logstream (SYSTEM) << "Problem with restart from " << opt->getValue ('r') << "" << endl; #ifdef OAEXTEND_MPI MPI_Abort (MPI_COMM_WORLD, 1); #endif exit (1); } if (dosort) { double Ttmp = get_time_ms (); sort (solutions.begin (), solutions.end ()); // solutions.sort(); log_print (QUIET, " sorting of initial solutions: %.3f [s]\n", get_time_ms () - Ttmp); } // check that oaconfig agrees with loaded arrays if (solutions.size () > 0) { if (ad->N != solutions[0].n_rows) { printf ("Problem: oaconfig does not agree with loaded arrays!\n"); // free_sols(solutions); ?? solutions.clear (); } } } else { // starting with root if (check_divisibility (ad) == false) { log_print (SYSTEM, "ERROR: Failed divisibility test!\n"); #ifdef OAEXTEND_MPI MPI_Abort (MPI_COMM_WORLD, 1); #endif exit (1); } create_root (ad, solutions); col_start = ad->strength; } /*-----------MAIN EXTENSION LOOP-------------*/ log_print (SYSTEM, "M: running with %d procs\n", n_processors); maxk = std::min (maxk, ad->ncols); time_t seconds; for (colindex_t current_col = col_start; current_col < maxk; current_col++) { fflush (stdout); arraydata_t *adcol = new arraydata_t (ad, current_col + 1); if (streaming) { string fname = resultprefix; fname += "-streaming"; fname += "-" + oafilestring (ad); logstream (NORMAL) << "oaextend: streaming mode: create file " << fname << std::endl; int nb = arrayfile_t::arrayNbits (*ad); oaextend.storefile.createfile (fname, adcol->N, ad->ncols, -1, ABINARY, nb); } log_print (SYSTEM, "Starting with column %d (%d, total time: %.2f [s])\n", current_col + 1, (int)solutions.size (), get_time_ms () - Tstart); nr_extensions = 0; arraylist_t::const_iterator cur_extension; int csol = 0; for (cur_extension = solutions.begin (); cur_extension != solutions.end (); cur_extension++) { print_progress (csol, solutions, extensions, Tstart, current_col); logstream (NORMAL) << cur_extension[0]; if (n_processors == 1) { nr_extensions += extend_array (*cur_extension, adcol, current_col, extensions, oaextend); } else { #ifdef OAEXTEND_MPI throw_runtime_exception("mpi version of oextend is no longer supported"); double Ttmp = get_time_ms (); int slave = collect_solutions_single (extensions, adcol); log_print (DEBUG, " time: %.2f, collect time %.2f\n", (get_time_ms () - Tstart), (get_time_ms () - Ttmp)); /* OPTIMIZE: send multiple arrays to slave 1 once step */ extend_array_mpi (cur_extension->array, 1, adcol, current_col, slave); #endif } #ifdef OAEXTEND_MPI if ((csol + 1) % nsolsync == 0) { collect_solutions_all (extensions, adcol); } #endif // OPTIMIZE: periodically write part of the solutions to disk csol++; /* increase current solution */ } #ifdef OAEXTEND_MPI collect_solutions_all (extensions, adcol); #endif if (checkloglevel (NORMAL)) { csol = 0; for (cur_extension = extensions.begin (); cur_extension != extensions.end (); cur_extension++) { log_print (DEBUG, "%i: -----\n", ++csol); logstream (DEBUG) << cur_extension[0]; } } if (dosort) { log_print (DEBUG, "Sorting solutions, necessary for multi-processor code\n"); double Ttmp = get_time_ms (); sort (extensions.begin (), extensions.end ()); log_print (DEBUG, " sorting time: %.3f [s]\n", get_time_ms () - Ttmp); } save_arrays (extensions, adcol, resultprefix, mode); solutions.swap (extensions); // swap old and newly found solutions extensions.clear (); // clear old to free up space for new extensions log_print (SYSTEM, "Done with column %i, total of %i solutions (time %.2f s))\n", current_col + 1, (int)solutions.size (), get_time_ms () - Tstart); delete adcol; #ifdef OAANALYZE_DISCR logstream (NORMAL) << "Discriminant: " << endl; print_discriminant (ad->N, current_col + 1); #endif } /*------------------------*/ time (&seconds); struct tm *tminfo; tminfo = localtime (&seconds); log_print (SYSTEM, "TIME: %.2f s, %s", get_time_ms () - Tstart, asctime (tminfo)); logstream (QUIET) << "#time end: " << currenttime () << std::endl; logstream (QUIET) << "#time total: " << printfstring ("%.1f", get_time_ms () - Tstart) << " [s]" << std::endl; solutions.clear (); delete ad; #ifdef OAEXTEND_MPI stop_slaves (); #endif } delete opt; } /* end of master code */ #ifdef OAEXTEND_MPI MPI_Finalize (); #endif return 0; }
static int create_subprocess(JNIEnv* env, char const* cmd, char const* cwd, char* const argv[], char** envp, int* pProcessId) { int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC); if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx"); #ifdef LACKS_PTSNAME_R char* devname; #else char devname[64]; #endif if (grantpt(ptm) || unlockpt(ptm) || #ifdef LACKS_PTSNAME_R (devname = ptsname(ptm)) == NULL #else ptsname_r(ptm, devname, sizeof(devname)) #endif ) { return throw_runtime_exception(env, "Cannot grantpt()/unlockpt()/ptsname_r() on /dev/ptmx"); } // Enable UTF-8 mode and disable flow control to prevent Ctrl+S from locking up the display. struct termios tios; tcgetattr(ptm, &tios); tios.c_iflag |= IUTF8; tios.c_iflag &= ~(IXON | IXOFF); tcsetattr(ptm, TCSANOW, &tios); /** Set initial winsize (better too small than too large). */ struct winsize sz = { .ws_row = 20, .ws_col = 20 }; ioctl(ptm, TIOCSWINSZ, &sz); pid_t pid = fork(); if (pid < 0) { return throw_runtime_exception(env, "Fork failed"); } else if (pid > 0) { *pProcessId = (int) pid; return ptm; } else { // Clear signals which the Android java process may have blocked: sigset_t signals_to_unblock; sigfillset(&signals_to_unblock); sigprocmask(SIG_UNBLOCK, &signals_to_unblock, 0); close(ptm); setsid(); int pts = open(devname, O_RDWR); if (pts < 0) exit(-1); dup2(pts, 0); dup2(pts, 1); dup2(pts, 2); DIR* self_dir = opendir("/proc/self/fd"); if (self_dir != NULL) { int self_dir_fd = dirfd(self_dir); struct dirent* entry; while ((entry = readdir(self_dir)) != NULL) { int fd = atoi(entry->d_name); if(fd > 2 && fd != self_dir_fd) close(fd); } closedir(self_dir); } clearenv(); if (envp) for (; *envp; ++envp) putenv(*envp); if (chdir(cwd) != 0) { char* error_message; // No need to free asprintf()-allocated memory since doing execvp() or exit() below. if (asprintf(&error_message, "chdir(\"%s\")", cwd) == -1) error_message = "chdir()"; perror(error_message); fflush(stderr); } execvp(cmd, argv); // Show terminal output about failing exec() call: char* error_message; if (asprintf(&error_message, "exec(\"%s\")", cmd) == -1) error_message = "exec()"; perror(error_message); _exit(1); } } JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(JNIEnv* env, jclass TERMUX_UNUSED(clazz), jstring cmd, jstring cwd, jobjectArray args, jobjectArray envVars, jintArray processIdArray) { jsize size = args ? (*env)->GetArrayLength(env, args) : 0; char** argv = NULL; if (size > 0) { argv = (char**) malloc((size + 1) * sizeof(char*)); if (!argv) return throw_runtime_exception(env, "Couldn't allocate argv array"); for (int i = 0; i < size; ++i) { jstring arg_java_string = (jstring) (*env)->GetObjectArrayElement(env, args, i); char const* arg_utf8 = (*env)->GetStringUTFChars(env, arg_java_string, NULL); if (!arg_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for argv"); argv[i] = strdup(arg_utf8); (*env)->ReleaseStringUTFChars(env, arg_java_string, arg_utf8); } argv[size] = NULL; } size = envVars ? (*env)->GetArrayLength(env, envVars) : 0; char** envp = NULL; if (size > 0) { envp = (char**) malloc((size + 1) * sizeof(char *)); if (!envp) return throw_runtime_exception(env, "malloc() for envp array failed"); for (int i = 0; i < size; ++i) { jstring env_java_string = (jstring) (*env)->GetObjectArrayElement(env, envVars, i); char const* env_utf8 = (*env)->GetStringUTFChars(env, env_java_string, 0); if (!env_utf8) return throw_runtime_exception(env, "GetStringUTFChars() failed for env"); envp[i] = strdup(env_utf8); (*env)->ReleaseStringUTFChars(env, env_java_string, env_utf8); } envp[size] = NULL; } int procId = 0; char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL); char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL); int ptm = create_subprocess(env, cmd_utf8, cmd_cwd, argv, envp, &procId); (*env)->ReleaseStringUTFChars(env, cmd, cmd_utf8); (*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd); if (argv) { for (char** tmp = argv; *tmp; ++tmp) free(*tmp); free(argv); } if (envp) { for (char** tmp = envp; *tmp; ++tmp) free(*tmp); free(envp); } int* pProcId = (int*) (*env)->GetPrimitiveArrayCritical(env, processIdArray, NULL); if (!pProcId) return throw_runtime_exception(env, "JNI call GetPrimitiveArrayCritical(processIdArray, &isCopy) failed"); *pProcId = procId; (*env)->ReleasePrimitiveArrayCritical(env, processIdArray, pProcId, 0); return ptm; }