// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package google.registry.dns;

import static google.registry.config.RegistryEnvironment.PRODUCTION;

import com.google.common.collect.ImmutableSet;
import com.google.monitoring.metrics.DistributionFitter;
import com.google.monitoring.metrics.EventMetric;
import com.google.monitoring.metrics.ExponentialFitter;
import com.google.monitoring.metrics.FibonacciFitter;
import com.google.monitoring.metrics.IncrementableMetric;
import com.google.monitoring.metrics.LabelDescriptor;
import com.google.monitoring.metrics.MetricRegistryImpl;
import google.registry.config.RegistryEnvironment;
import javax.inject.Inject;
import org.joda.time.Duration;

/** DNS instrumentation. */
// TODO(b/67947699):Once load testing is done, revisit these to rename them and delete the ones that
// we don't expect to need long-term.
public class DnsMetrics {

  /** Disposition of a publish request. */
  public enum PublishStatus { ACCEPTED, REJECTED }

  /** Disposition of writer.commit(). */
  public enum CommitStatus { SUCCESS, FAILURE }

  /** Disposition of the publish action. */
  public enum ActionStatus { SUCCESS, COMMIT_FAILURE, LOCK_FAILURE, BAD_WRITER, BAD_LOCK_INDEX }

  private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS_FOR_PUBLISH_REQUESTS =
      ImmutableSet.of(
          LabelDescriptor.create("tld", "TLD"),
          LabelDescriptor.create(
              "status", "Whether the publish request was accepted or rejected."));

  private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS_FOR_COMMIT =
      ImmutableSet.of(
          LabelDescriptor.create("tld", "TLD"),
          LabelDescriptor.create("status", "Whether writer.commit() succeeded or failed."),
          LabelDescriptor.create("dnsWriter", "The DnsWriter used."));

  private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS_FOR_LATENCY =
      ImmutableSet.of(
          LabelDescriptor.create("tld", "TLD"),
          LabelDescriptor.create("status", "Whether the publish succeeded, or why it failed."),
          LabelDescriptor.create("dnsWriter", "The DnsWriter used."));

  // Finer-grained fitter than the DEFAULT_FITTER, allows values between 100 ms and just over 29
  // hours.
  private static final DistributionFitter EXPONENTIAL_FITTER =
      ExponentialFitter.create(20, 2.0, 100.0);

  // Fibonacci fitter more suitible for integer-type values. Allows values between 0 and 10946,
  // which is the 21th Fibonacci number.
  private static final DistributionFitter FIBONACCI_FITTER =
      FibonacciFitter.create(10946);

  private static final IncrementableMetric publishDomainRequests =
      MetricRegistryImpl.getDefault()
          .newIncrementableMetric(
              "/dns/publish_domain_requests",
              "count of publishDomain requests",
              "count",
              LABEL_DESCRIPTORS_FOR_PUBLISH_REQUESTS);

  private static final IncrementableMetric publishHostRequests =
      MetricRegistryImpl.getDefault()
          .newIncrementableMetric(
              "/dns/publish_host_requests",
              "count of publishHost requests",
              "count",
              LABEL_DESCRIPTORS_FOR_PUBLISH_REQUESTS);

  private static final IncrementableMetric commitCount =
      MetricRegistryImpl.getDefault()
          .newIncrementableMetric(
              "/dns/commit_requests",
              "Count of writer.commit() calls",
              "count",
              LABEL_DESCRIPTORS_FOR_COMMIT);

  private static final IncrementableMetric domainsCommittedCount =
      MetricRegistryImpl.getDefault()
          .newIncrementableMetric(
              "/dns/domains_committed",
              "Count of domains committed",
              "count",
              LABEL_DESCRIPTORS_FOR_COMMIT);

  private static final IncrementableMetric hostsCommittedCount =
      MetricRegistryImpl.getDefault()
          .newIncrementableMetric(
              "/dns/hosts_committed",
              "Count of hosts committed",
              "count",
              LABEL_DESCRIPTORS_FOR_COMMIT);

  private static final EventMetric processingTimePerCommitDist =
      MetricRegistryImpl.getDefault()
          .newEventMetric(
              "/dns/per_batch/processing_time",
              "publishDnsUpdates Processing Time",
              "milliseconds",
              LABEL_DESCRIPTORS_FOR_COMMIT,
              EXPONENTIAL_FITTER);

  private static final EventMetric normalizedProcessingTimePerCommitDist =
      MetricRegistryImpl.getDefault()
          .newEventMetric(
              "/dns/per_batch/processing_time_per_dns_update",
              "publishDnsUpdates Processing Time, divided by the batch size",
              "milliseconds",
              LABEL_DESCRIPTORS_FOR_COMMIT,
              EXPONENTIAL_FITTER);

  private static final EventMetric totalBatchSizePerCommitDist =
      MetricRegistryImpl.getDefault()
          .newEventMetric(
              "/dns/per_batch/batch_size",
              "Number of hosts and domains committed in each publishDnsUpdates",
              "count",
              LABEL_DESCRIPTORS_FOR_COMMIT,
              FIBONACCI_FITTER);

  private static final EventMetric processingTimePerItemDist =
      MetricRegistryImpl.getDefault()
          .newEventMetric(
              "/dns/per_item/processing_time",
              "publishDnsUpdates Processing Time",
              "milliseconds",
              LABEL_DESCRIPTORS_FOR_COMMIT,
              EXPONENTIAL_FITTER);

  private static final EventMetric normalizedProcessingTimePerItemDist =
      MetricRegistryImpl.getDefault()
          .newEventMetric(
              "/dns/per_item/processing_time_per_dns_update",
              "publishDnsUpdates Processing Time, divided by the batch size",
              "milliseconds",
              LABEL_DESCRIPTORS_FOR_COMMIT,
              EXPONENTIAL_FITTER);

  private static final EventMetric totalBatchSizePerItemDist =
      MetricRegistryImpl.getDefault()
          .newEventMetric(
              "/dns/per_item/batch_size",
              "Batch sizes for hosts and domains",
              "count",
              LABEL_DESCRIPTORS_FOR_COMMIT,
              FIBONACCI_FITTER);

  private static final EventMetric updateRequestLatency =
      MetricRegistryImpl.getDefault()
          .newEventMetric(
              "/dns/update_latency",
              "Time elapsed since refresh request was created until it was published",
              "milliseconds",
              LABEL_DESCRIPTORS_FOR_LATENCY,
              EXPONENTIAL_FITTER);

  private static final EventMetric publishQueueDelay =
      MetricRegistryImpl.getDefault()
          .newEventMetric(
              "/dns/publish_queue_delay",
              "Time elapsed since the publishDnsUpdates action was created until it was executed",
              "milliseconds",
              LABEL_DESCRIPTORS_FOR_LATENCY,
              EXPONENTIAL_FITTER);

  @Inject
  DnsMetrics() {}

  /**
   * Increment a monotonic counter that tracks calls to {@link
   * google.registry.dns.writer.DnsWriter#publishDomain(String)}, per TLD.
   */
  public void incrementPublishDomainRequests(String tld, long numRequests, PublishStatus status) {
    if (numRequests > 0) {
      publishDomainRequests.incrementBy(numRequests, tld, status.name());
    }
  }

  /**
   * Increment a monotonic counter that tracks calls to {@link
   * google.registry.dns.writer.DnsWriter#publishHost(String)}, per TLD.
   */
  public void incrementPublishHostRequests(String tld, long numRequests, PublishStatus status) {
    if (numRequests > 0) {
      publishHostRequests.incrementBy(numRequests, tld, status.name());
    }
  }

  /**
   * Measures information about the entire batched commit, per TLD.
   *
   *
The information includes running times (per item and per commit), and batch sizes (per item
   * and per commit)
   *
   *
This is to be used for load testing the system, and will not measure anything in prod.
   */
  void recordCommit(
      String tld,
      String dnsWriter,
      CommitStatus status,
      Duration processingDuration,
      int numberOfDomains,
      int numberOfHosts) {
    commitCount.increment(tld, status.name(), dnsWriter);
    domainsCommittedCount.incrementBy(numberOfDomains, tld, status.name(), dnsWriter);
    hostsCommittedCount.incrementBy(numberOfHosts, tld, status.name(), dnsWriter);

    // We don't want to record the following metrics in production, as they are quite expensive
    if (RegistryEnvironment.get().equals(PRODUCTION)) {
      return;
    }

    int batchSize = numberOfDomains + numberOfHosts;

    processingTimePerCommitDist.record(
        processingDuration.getMillis(), tld, status.name(), dnsWriter);
    processingTimePerItemDist.record(
        processingDuration.getMillis(), batchSize, tld, status.name(), dnsWriter);

    if (batchSize > 0) {
      normalizedProcessingTimePerCommitDist.record(
          (double) processingDuration.getMillis() / batchSize,
          tld, status.name(), dnsWriter);
      normalizedProcessingTimePerItemDist.record(
          (double) processingDuration.getMillis() / batchSize,
          batchSize,
          tld, status.name(), dnsWriter);
    }

    totalBatchSizePerCommitDist.record(batchSize, tld, status.name(), dnsWriter);

    totalBatchSizePerItemDist.record(batchSize, batchSize, tld, status.name(), dnsWriter);
  }

  void recordActionResult(
      String tld,
      String dnsWriter,
      ActionStatus status,
      int numberOfItems,
      Duration timeSinceUpdateRequest,
      Duration timeSinceActionEnqueued) {
    updateRequestLatency.record(
        timeSinceUpdateRequest.getMillis(), numberOfItems, tld, status.name(), dnsWriter);
    publishQueueDelay.record(timeSinceActionEnqueued.getMillis(), tld, status.name(), dnsWriter);
  }
}

{'repo_name': 'google/nomulus', 'stars': '1417', 'repo_language': 'Java', 'file_name': 'README.md', 'mime_type': 'text/plain', 'hash': 7851446466009233786, 'source_dataset': 'data'}


# encoding: utf-8
# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""Text processor tests."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import tensorflow as tf

from tensorflow.contrib.learn.python.learn.preprocessing import CategoricalVocabulary
from tensorflow.contrib.learn.python.learn.preprocessing import text

class TextTest(tf.test.TestCase):
  """Text processor tests."""

  def testTokenizer(self):
    words = text.tokenizer(
        ["a b c", "a\nb\nc", "a, b - c", "фыв выф", "你好 怎么样"])
    self.assertEqual(
        list(words), [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "-", "c"],
                      ["фыв", "выф"], ["你好", "怎么样"]])

  def testByteProcessor(self):
    processor = text.ByteProcessor(max_document_length=8)
    inp = ["abc", "фыва", "фыва", b"abc", "12345678901234567890"]
    res = list(processor.fit_transform(inp))
    self.assertAllEqual(res, [[97, 98, 99, 0, 0, 0, 0, 0],
                              [209, 132, 209, 139, 208, 178, 208, 176],
                              [209, 132, 209, 139, 208, 178, 208, 176],
                              [97, 98, 99, 0, 0, 0, 0, 0],
                              [49, 50, 51, 52, 53, 54, 55, 56]])
    res = list(processor.reverse(res))
    self.assertAllEqual(res, ["abc", "фыва", "фыва", "abc", "12345678"])

  def testVocabularyProcessor(self):
    vocab_processor = text.VocabularyProcessor(max_document_length=4,
                                               min_frequency=1)
    tokens = vocab_processor.fit_transform(["a b c", "a\nb\nc", "a, b - c"])
    self.assertAllEqual(
        list(tokens), [[1, 2, 3, 0], [1, 2, 3, 0], [1, 2, 0, 3]])

  def testVocabularyProcessorSaveRestore(self):
    filename = tf.test.get_temp_dir() + "test.vocab"
    vocab_processor = text.VocabularyProcessor(max_document_length=4,
                                               min_frequency=1)
    tokens = vocab_processor.fit_transform(["a b c", "a\nb\nc", "a, b - c"])
    vocab_processor.save(filename)
    new_vocab = text.VocabularyProcessor.restore(filename)
    tokens = new_vocab.transform(["a b c"])
    self.assertAllEqual(list(tokens), [[1, 2, 3, 0]])

  def testExistingVocabularyProcessor(self):
    vocab = CategoricalVocabulary()
    vocab.get("A")
    vocab.get("B")
    vocab.freeze()
    vocab_processor = text.VocabularyProcessor(max_document_length=4,
                                               vocabulary=vocab,
                                               tokenizer_fn=list)
    tokens = vocab_processor.fit_transform(["ABC", "CBABAF"])
    self.assertAllEqual(list(tokens), [[1, 2, 0, 0], [0, 2, 1, 2]])

if __name__ == "__main__":
  tf.test.main()

{'repo_name': 'tobegit3hub/deep_image_model', 'stars': '102', 'repo_language': 'Python', 'file_name': 'convert_tfrecords.py', 'mime_type': 'text/x-python', 'hash': 7304509701759496404, 'source_dataset': 'data'}


package com.networknt.petstore.handler;

import com.networknt.handler.LightHttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import java.util.HashMap;
import java.util.Map;

public class PetsPetIdDeleteHandler implements LightHttpHandler {

    @Override
    public void handleRequest(HttpServerExchange exchange) throws Exception {
        exchange.getResponseHeaders().add(new HttpString("Content-Type"), "application/json");
        exchange.setStatusCode(200);
        exchange.getResponseSender().send("{\"id\":1,\"name\":\"Jessica Right\",\"tag\":\"pet\"}");
    }
}

{'repo_name': 'networknt/light-example-4j', 'stars': '131', 'repo_language': 'Java', 'file_name': 'logback.xml', 'mime_type': 'text/xml', 'hash': -5286962158396119955, 'source_dataset': 'data'}


Что это такое? Это система сборки Openwrt переделанаая на сборку Entware разных архитектур.

Были внесены следующие изменения (часть взята из патчей Entware, часть добавлена):

1. Makefile - удалены последние этапы - $(package/stamp-install) $(target/stamp-install). make заканчивает на package/compile
2. rules.mk - изменение путей в TARGET_CPPFLAGS и TARGET_LDFLAGS.
              Установка dynamic-linker в зависимости от архитектуры и libc. Для musl не делал, для mipsel + glibc не проверял.
              Выкинул задание LIBRPC и LIBRPC_DEPENDS - librpc не собирается и ненужна (musl - неизвестно ???)
3. scripts/download.pl (добавлены зеркала entware)
4. scripts/ipkg-make-index.sh - libc теперь индексируется в package/index
5. scripts/rstrip.sh - выкинул удаление RPATH
6. папка include
autotools.mk usr -> opt
cmake.mk     usr -> opt
kernel-build.mk - выброшена сборка ядра и модулей
kernel-version.mk - добавлены 2.6.32 и 2.6.36, 2.6.22. Выброшены 3.x. 2.6.22.19 не скачивается,
                    md5 не нужно, задается через CONFIG_EXTERNAL_KERNEL_TREE
nls.mk       usr -> opt
package-defaults.mk usr -> opt
package-ipkg.mk     usr -> opt и другие изменения из entware
package.mk          usr -> opt
target.mk           набор пакетов по умолчанию (косметика)
7. tools
ent-kernel - псевдо тул, скачивает и распаковывает ядро энтузиастов
ppl/patches/010-ptrdiff.patch
8. target
выкинул target'ы openwrt и добавил свои. Обращаю внимание, что версия ядра задается через KERNEL_PATCHVER,
остальное делает include/kernel-version.mk. Можно использовать свои ядра, через задание пути CONFIG_EXTERNAL_KERNEL_TREE
Makefile в подпапке Image у новых таргетов не должен ничего вызывать.
9. toolchain (тут много изменений)
Выкинуты многие версии binutils, gcc, clib и добавлены новые
binutils - оставил 2.25.1, может имеет смыл добавить 2.24 (не Linaro)
gcc - оставил 5.2, добавил 4.9.3 и 4.8.5. Остальные выкинул
libc - добавил glibc 2.22 (release), добавил при сборке --enable-obsolete-rpc
Выкинул все Uclibc, оставил Uclibc-ng и обновил до 1.0.7 (поменял config - uClibc/config-ng-1.0.7/common поближе к тулчену
энтузиастов). musl не трогал.
Немного изменил kernel-headers/Makefile (для энтузиастовского ядра)
10. packages
Выкинул
firmware
boot - кроме kexec-tools
убрал аттрибут hidden у некоторых пакетов
(TODO) Дурацкая модификация gdb на случай сборки после binutils.
Раньше через PKG_BUILD_DEPENDS было (это вернуть после добавления legacy вариантов)
ncurses -> 6.0 плюс девелоперсие патчи. Иначе под  gcc 5.2 не собрать.
другие изменения от Entware (usr->opt) то be revised

Тулчейн с uclibc-ng собирается только при выборе gcc 5.2. Поэтому 5.2 выбрал для всех архитектур (однообразие)

Проблемы, замечания,TODO

Cтатическая линковка в случае glibc 2.22 по умолчанию непроходит, чтобы прошла нужно перед --static задать "-lc -lgcc_eh",
для варианта с uclibc_ng это не нужно.

Многие пакеты (вариант mipselsf) захотели при конфигурации libssp
В таких случаях добавлял
TARGET_LDFLAGS += -lssp
и в DEPENDS +libssp.
Можно наоборот попробовать отключить через флаги gcc
TARGET_CFLAGS += \
<------>-U_FORTIFY_SOURCE  -fno-stack-protector \

Нужно сделать legacy варианты некоторых пакетов и прописать в зависимости от TARGET_mipselsf

Этап gcc_initial (make install-gcc install-target-libgcc) создает битую символическую ссылку lib в staging_dir/toolchain....

{'repo_name': 'Entware/Entware-ng', 'stars': '1123', 'repo_language': 'C', 'file_name': 'Makefile', 'mime_type': 'text/plain', 'hash': 3658207379298925790, 'source_dataset': 'data'}


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>com.fasterxml.jackson.databind.deser (jackson-databind 2.11.0 API)</title>
<meta name="date" content="2020-04-25">
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Package

Next Package

Frames

No Frames

All Classes

Package com.fasterxml.jackson.databind.deser

Contains implementation classes of deserialization part of
 data binding.

See: Description

Interface Summary

Interface
Description

ContextualDeserializer

Add-on interface that JsonDeserializers can implement to get a callback
 that can be used to create contextual (context-dependent) instances of
 deserializer to use for  handling properties of supported type.

ContextualKeyDeserializer

Add-on interface that KeyDeserializers can implement to get a callback
 that can be used to create contextual instances of key deserializer to use for
 handling Map keys of supported type.

Deserializers

Interface that defines API for simple extensions that can provide additional deserializers
 for various types.

KeyDeserializers

Interface that defines API for simple extensions that can provide additional deserializers
 for deserializer Map keys of various types, from JSON property names.

NullValueProvider

Helper interface implemented by classes that are to be used as
 null providers during deserialization.

ResolvableDeserializer

Interface used to indicate deserializers that want to do post-processing
 after construction but before being returned to caller (and possibly cached)
 and used.

ValueInstantiator.Gettable

ValueInstantiators

Interface for providers of ValueInstantiator instances.

Class Summary

Class
Description

AbstractDeserializer

Deserializer only used for abstract types used as placeholders during polymorphic
 type handling deserialization.

BasicDeserializerFactory

Abstract factory base class that can provide deserializers for standard
 JDK classes, including collection classes and simple heuristics for
 "upcasting" common collection interface types
 (such as Collection).

BasicDeserializerFactory.ContainerDefaultMappings

Helper class to contain default mappings for abstract JDK Collection
 and Map types.

BeanDeserializer

Deserializer class that can deserialize instances of
 arbitrary bean objects, usually from JSON Object structs,

BeanDeserializerBase

Base class for BeanDeserializer.

BeanDeserializerBuilder

Builder class used for aggregating deserialization information about
 a POJO, in order to build a JsonDeserializer for deserializing
 instances.

BeanDeserializerFactory

Concrete deserializer factory class that adds full Bean deserializer
 construction logic using class introspection.

BeanDeserializerModifier

Abstract class that defines API for objects that can be registered
 to participate in constructing JsonDeserializer instances
 (via DeserializerFactory).

BuilderBasedDeserializer

Class that handles deserialization using a separate
 Builder class, which is used for data binding and
 produces actual deserialized value at the end
 of data binding.

CreatorProperty

This concrete sub-class implements property that is passed
 via Creator (constructor or static factory method).

DataFormatReaders

Alternative to DataFormatDetector that needs to be used when
 using data-binding.

DataFormatReaders.Match

Result class, similar to DataFormatMatcher

DefaultDeserializationContext

Complete DeserializationContext implementation that adds
 extended API for ObjectMapper (and ObjectReader)
 to call, as well as implements certain parts that base class
 has left abstract.

DefaultDeserializationContext.Impl

Actual full concrete implementation

DeserializationProblemHandler

This is the class that can be registered (via
 DeserializationConfig object owner by
 ObjectMapper) to get called when a potentially
 recoverable problem is encountered during deserialization
 process.

DeserializerCache

Class that defines caching layer between callers (like
 ObjectMapper,
 DeserializationContext)
 and classes that construct deserializers
 (DeserializerFactory).

DeserializerFactory

Abstract class that defines API used by DeserializationContext
 to construct actual
 JsonDeserializer instances (which are then cached by
 context and/or dedicated cache).

Deserializers.Base

Basic Deserializers implementation that implements all methods but provides
 no deserializers.

SettableAnyProperty

Class that represents a "wildcard" set method which can be used
 to generically set values of otherwise unmapped (aka "unknown")
 properties read from Json content.

SettableBeanProperty

Base class for deserializable properties of a bean: contains
 both type and name definitions, and reflection-based set functionality.

SettableBeanProperty.Delegating

Helper class that is designed to both make it easier to sub-class
 delegating subtypes and to reduce likelihood of breakage when
 new methods are added.

UnresolvedId

Helper class for UnresolvedForwardReference, to contain information about unresolved ids.

ValueInstantiator

Class that defines simple API implemented by objects that create value
 instances.

ValueInstantiator.Base

Partial ValueInstantiator implementation that is strongly recommended
 to be used instead of directly extending ValueInstantiator itself.

ValueInstantiators.Base

Basic "NOP" implementation that can be used as the base class for custom implementations.

Exception Summary

Exception
Description

UnresolvedForwardReference

Exception thrown during deserialization when there are object id that can't
 be resolved.

Package com.fasterxml.jackson.databind.deser Description

Contains implementation classes of deserialization part of
 data binding.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Package

Next Package

Frames

No Frames

All Classes

Copyright © 2008–2020 FasterXML. All rights reserved.

{'repo_name': 'FasterXML/jackson-databind', 'stars': '2575', 'repo_language': 'Java', 'file_name': 'package-use.html', 'mime_type': 'text/html', 'hash': 4094285917488142015, 'source_dataset': 'data'}


/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
/*
 * rseq-x86.h
 *
 * (C) Copyright 2016-2018 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
 */

#include <stdint.h>

#define RSEQ_SIG	0x53053053

#ifdef __x86_64__

#define rseq_smp_mb()	\
	__asm__ __volatile__ ("lock; addl $0,-128(%%rsp)" ::: "memory", "cc")
#define rseq_smp_rmb()	rseq_barrier()
#define rseq_smp_wmb()	rseq_barrier()

#define rseq_smp_load_acquire(p)					\
__extension__ ({							\
	__typeof(*p) ____p1 = RSEQ_READ_ONCE(*p);			\
	rseq_barrier();							\
	____p1;								\
})

#define rseq_smp_acquire__after_ctrl_dep()	rseq_smp_rmb()

#define rseq_smp_store_release(p, v)					\
do {									\
	rseq_barrier();							\
	RSEQ_WRITE_ONCE(*p, v);						\
} while (0)

#ifdef RSEQ_SKIP_FASTPATH
#include "rseq-skip.h"
#else /* !RSEQ_SKIP_FASTPATH */

#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,			\
				start_ip, post_commit_offset, abort_ip)	\
		".pushsection __rseq_table, \"aw\"\n\t"			\
		".balign 32\n\t"					\
		__rseq_str(label) ":\n\t"				\
		".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
		".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
		".popsection\n\t"

#define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
	__RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,		\
				(post_commit_ip - start_ip), abort_ip)

#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)		\
		RSEQ_INJECT_ASM(1)					\
		"leaq " __rseq_str(cs_label) "(%%rip), %%rax\n\t"	\
		"movq %%rax, %[" __rseq_str(rseq_cs) "]\n\t"		\
		__rseq_str(label) ":\n\t"

#define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)		\
		RSEQ_INJECT_ASM(2)					\
		"cmpl %[" __rseq_str(cpu_id) "], %[" __rseq_str(current_cpu_id) "]\n\t" \
		"jnz " __rseq_str(label) "\n\t"

#define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)		\
		".pushsection __rseq_failure, \"ax\"\n\t"		\
		/* Disassembler-friendly signature: nopl <sig>(%rip). */\
		".byte 0x0f, 0x1f, 0x05\n\t"				\
		".long " __rseq_str(RSEQ_SIG) "\n\t"			\
		__rseq_str(label) ":\n\t"				\
		teardown						\
		"jmp %l[" __rseq_str(abort_label) "]\n\t"		\
		".popsection\n\t"

#define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label)		\
		".pushsection __rseq_failure, \"ax\"\n\t"		\
		__rseq_str(label) ":\n\t"				\
		teardown						\
		"jmp %l[" __rseq_str(cmpfail_label) "]\n\t"		\
		".popsection\n\t"

static inline __attribute__((always_inline))
int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"cmpq %[v], %[expect]\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"cmpq %[v], %[expect]\n\t"
		"jnz %l[error2]\n\t"
#endif
		/* final store */
		"movq %[newv], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(5)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  [v]			"m" (*v),
		  [expect]		"r" (expect),
		  [newv]		"r" (newv)
		: "memory", "cc", "rax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

/*
 * Compare @v against @expectnot. When it does _not_ match, load @v
 * into @load, and store the content of *@v + voffp into @v.
 */
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
			       off_t voffp, intptr_t *load, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"movq %[v], %%rbx\n\t"
		"cmpq %%rbx, %[expectnot]\n\t"
		"je %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"movq %[v], %%rbx\n\t"
		"cmpq %%rbx, %[expectnot]\n\t"
		"je %l[error2]\n\t"
#endif
		"movq %%rbx, %[load]\n\t"
		"addq %[voffp], %%rbx\n\t"
		"movq (%%rbx), %%rbx\n\t"
		/* final store */
		"movq %%rbx, %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(5)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* final store input */
		  [v]			"m" (*v),
		  [expectnot]		"r" (expectnot),
		  [voffp]		"er" (voffp),
		  [load]		"m" (*load)
		: "memory", "cc", "rax", "rbx"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

static inline __attribute__((always_inline))
int rseq_addv(intptr_t *v, intptr_t count, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
#endif
		/* final store */
		"addq %[count], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(4)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* final store input */
		  [v]			"m" (*v),
		  [count]		"er" (count)
		: "memory", "cc", "rax"
		  RSEQ_INJECT_CLOBBER
		: abort
#ifdef RSEQ_COMPARE_TWICE
		  , error1
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
#endif
}

static inline __attribute__((always_inline))
int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
				 intptr_t *v2, intptr_t newv2,
				 intptr_t newv, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"cmpq %[v], %[expect]\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"cmpq %[v], %[expect]\n\t"
		"jnz %l[error2]\n\t"
#endif
		/* try store */
		"movq %[newv2], %[v2]\n\t"
		RSEQ_INJECT_ASM(5)
		/* final store */
		"movq %[newv], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(6)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* try store input */
		  [v2]			"m" (*v2),
		  [newv2]		"r" (newv2),
		  /* final store input */
		  [v]			"m" (*v),
		  [expect]		"r" (expect),
		  [newv]		"r" (newv)
		: "memory", "cc", "rax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

/* x86-64 is TSO. */
static inline __attribute__((always_inline))
int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
					 intptr_t *v2, intptr_t newv2,
					 intptr_t newv, int cpu)
{
	return rseq_cmpeqv_trystorev_storev(v, expect, v2, newv2, newv, cpu);
}

static inline __attribute__((always_inline))
int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
			      intptr_t *v2, intptr_t expect2,
			      intptr_t newv, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"cmpq %[v], %[expect]\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
		"cmpq %[v2], %[expect2]\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(5)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"cmpq %[v], %[expect]\n\t"
		"jnz %l[error2]\n\t"
		"cmpq %[v2], %[expect2]\n\t"
		"jnz %l[error3]\n\t"
#endif
		/* final store */
		"movq %[newv], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(6)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* cmp2 input */
		  [v2]			"m" (*v2),
		  [expect2]		"r" (expect2),
		  /* final store input */
		  [v]			"m" (*v),
		  [expect]		"r" (expect),
		  [newv]		"r" (newv)
		: "memory", "cc", "rax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2, error3
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("1st expected value comparison failed");
error3:
	rseq_bug("2nd expected value comparison failed");
#endif
}

static inline __attribute__((always_inline))
int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
				 void *dst, void *src, size_t len,
				 intptr_t newv, int cpu)
{
	uint64_t rseq_scratch[3];

	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		"movq %[src], %[rseq_scratch0]\n\t"
		"movq %[dst], %[rseq_scratch1]\n\t"
		"movq %[len], %[rseq_scratch2]\n\t"
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"cmpq %[v], %[expect]\n\t"
		"jnz 5f\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
		"cmpq %[v], %[expect]\n\t"
		"jnz 7f\n\t"
#endif
		/* try memcpy */
		"test %[len], %[len]\n\t" \
		"jz 333f\n\t" \
		"222:\n\t" \
		"movb (%[src]), %%al\n\t" \
		"movb %%al, (%[dst])\n\t" \
		"inc %[src]\n\t" \
		"inc %[dst]\n\t" \
		"dec %[len]\n\t" \
		"jnz 222b\n\t" \
		"333:\n\t" \
		RSEQ_INJECT_ASM(5)
		/* final store */
		"movq %[newv], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(6)
		/* teardown */
		"movq %[rseq_scratch2], %[len]\n\t"
		"movq %[rseq_scratch1], %[dst]\n\t"
		"movq %[rseq_scratch0], %[src]\n\t"
		RSEQ_ASM_DEFINE_ABORT(4,
			"movq %[rseq_scratch2], %[len]\n\t"
			"movq %[rseq_scratch1], %[dst]\n\t"
			"movq %[rseq_scratch0], %[src]\n\t",
			abort)
		RSEQ_ASM_DEFINE_CMPFAIL(5,
			"movq %[rseq_scratch2], %[len]\n\t"
			"movq %[rseq_scratch1], %[dst]\n\t"
			"movq %[rseq_scratch0], %[src]\n\t",
			cmpfail)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_DEFINE_CMPFAIL(6,
			"movq %[rseq_scratch2], %[len]\n\t"
			"movq %[rseq_scratch1], %[dst]\n\t"
			"movq %[rseq_scratch0], %[src]\n\t",
			error1)
		RSEQ_ASM_DEFINE_CMPFAIL(7,
			"movq %[rseq_scratch2], %[len]\n\t"
			"movq %[rseq_scratch1], %[dst]\n\t"
			"movq %[rseq_scratch0], %[src]\n\t",
			error2)
#endif
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* final store input */
		  [v]			"m" (*v),
		  [expect]		"r" (expect),
		  [newv]		"r" (newv),
		  /* try memcpy input */
		  [dst]			"r" (dst),
		  [src]			"r" (src),
		  [len]			"r" (len),
		  [rseq_scratch0]	"m" (rseq_scratch[0]),
		  [rseq_scratch1]	"m" (rseq_scratch[1]),
		  [rseq_scratch2]	"m" (rseq_scratch[2])
		: "memory", "cc", "rax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

/* x86-64 is TSO. */
static inline __attribute__((always_inline))
int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
					 void *dst, void *src, size_t len,
					 intptr_t newv, int cpu)
{
	return rseq_cmpeqv_trymemcpy_storev(v, expect, dst, src, len,
					    newv, cpu);
}

#endif /* !RSEQ_SKIP_FASTPATH */

#elif __i386__

#define rseq_smp_mb()	\
	__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")
#define rseq_smp_rmb()	\
	__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")
#define rseq_smp_wmb()	\
	__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")

#define rseq_smp_load_acquire(p)					\
__extension__ ({							\
	__typeof(*p) ____p1 = RSEQ_READ_ONCE(*p);			\
	rseq_smp_mb();							\
	____p1;								\
})

#define rseq_smp_acquire__after_ctrl_dep()	rseq_smp_rmb()

#define rseq_smp_store_release(p, v)					\
do {									\
	rseq_smp_mb();							\
	RSEQ_WRITE_ONCE(*p, v);						\
} while (0)

#ifdef RSEQ_SKIP_FASTPATH
#include "rseq-skip.h"
#else /* !RSEQ_SKIP_FASTPATH */

/*
 * Use eax as scratch register and take memory operands as input to
 * lessen register pressure. Especially needed when compiling in O0.
 */
#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,			\
				start_ip, post_commit_offset, abort_ip)	\
		".pushsection __rseq_table, \"aw\"\n\t"			\
		".balign 32\n\t"					\
		__rseq_str(label) ":\n\t"				\
		".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
		".long " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \
		".popsection\n\t"

#define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
	__RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,		\
				(post_commit_ip - start_ip), abort_ip)

#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)		\
		RSEQ_INJECT_ASM(1)					\
		"movl $" __rseq_str(cs_label) ", %[rseq_cs]\n\t"	\
		__rseq_str(label) ":\n\t"

#define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)		\
		RSEQ_INJECT_ASM(2)					\
		"cmpl %[" __rseq_str(cpu_id) "], %[" __rseq_str(current_cpu_id) "]\n\t" \
		"jnz " __rseq_str(label) "\n\t"

#define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)		\
		".pushsection __rseq_failure, \"ax\"\n\t"		\
		/* Disassembler-friendly signature: nopl <sig>. */	\
		".byte 0x0f, 0x1f, 0x05\n\t"				\
		".long " __rseq_str(RSEQ_SIG) "\n\t"			\
		__rseq_str(label) ":\n\t"				\
		teardown						\
		"jmp %l[" __rseq_str(abort_label) "]\n\t"		\
		".popsection\n\t"

#define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label)		\
		".pushsection __rseq_failure, \"ax\"\n\t"		\
		__rseq_str(label) ":\n\t"				\
		teardown						\
		"jmp %l[" __rseq_str(cmpfail_label) "]\n\t"		\
		".popsection\n\t"

static inline __attribute__((always_inline))
int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"cmpl %[v], %[expect]\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"cmpl %[v], %[expect]\n\t"
		"jnz %l[error2]\n\t"
#endif
		/* final store */
		"movl %[newv], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(5)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  [v]			"m" (*v),
		  [expect]		"r" (expect),
		  [newv]		"r" (newv)
		: "memory", "cc", "eax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

/*
 * Compare @v against @expectnot. When it does _not_ match, load @v
 * into @load, and store the content of *@v + voffp into @v.
 */
static inline __attribute__((always_inline))
int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
			       off_t voffp, intptr_t *load, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"movl %[v], %%ebx\n\t"
		"cmpl %%ebx, %[expectnot]\n\t"
		"je %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"movl %[v], %%ebx\n\t"
		"cmpl %%ebx, %[expectnot]\n\t"
		"je %l[error2]\n\t"
#endif
		"movl %%ebx, %[load]\n\t"
		"addl %[voffp], %%ebx\n\t"
		"movl (%%ebx), %%ebx\n\t"
		/* final store */
		"movl %%ebx, %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(5)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* final store input */
		  [v]			"m" (*v),
		  [expectnot]		"r" (expectnot),
		  [voffp]		"ir" (voffp),
		  [load]		"m" (*load)
		: "memory", "cc", "eax", "ebx"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

static inline __attribute__((always_inline))
int rseq_addv(intptr_t *v, intptr_t count, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
#endif
		/* final store */
		"addl %[count], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(4)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* final store input */
		  [v]			"m" (*v),
		  [count]		"ir" (count)
		: "memory", "cc", "eax"
		  RSEQ_INJECT_CLOBBER
		: abort
#ifdef RSEQ_COMPARE_TWICE
		  , error1
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
#endif
}

static inline __attribute__((always_inline))
int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
				 intptr_t *v2, intptr_t newv2,
				 intptr_t newv, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"cmpl %[v], %[expect]\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"cmpl %[v], %[expect]\n\t"
		"jnz %l[error2]\n\t"
#endif
		/* try store */
		"movl %[newv2], %%eax\n\t"
		"movl %%eax, %[v2]\n\t"
		RSEQ_INJECT_ASM(5)
		/* final store */
		"movl %[newv], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(6)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* try store input */
		  [v2]			"m" (*v2),
		  [newv2]		"m" (newv2),
		  /* final store input */
		  [v]			"m" (*v),
		  [expect]		"r" (expect),
		  [newv]		"r" (newv)
		: "memory", "cc", "eax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

static inline __attribute__((always_inline))
int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
					 intptr_t *v2, intptr_t newv2,
					 intptr_t newv, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"movl %[expect], %%eax\n\t"
		"cmpl %[v], %%eax\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"movl %[expect], %%eax\n\t"
		"cmpl %[v], %%eax\n\t"
		"jnz %l[error2]\n\t"
#endif
		/* try store */
		"movl %[newv2], %[v2]\n\t"
		RSEQ_INJECT_ASM(5)
		"lock; addl $0,-128(%%esp)\n\t"
		/* final store */
		"movl %[newv], %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(6)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* try store input */
		  [v2]			"m" (*v2),
		  [newv2]		"r" (newv2),
		  /* final store input */
		  [v]			"m" (*v),
		  [expect]		"m" (expect),
		  [newv]		"r" (newv)
		: "memory", "cc", "eax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif

}

static inline __attribute__((always_inline))
int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
			      intptr_t *v2, intptr_t expect2,
			      intptr_t newv, int cpu)
{
	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"cmpl %[v], %[expect]\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(4)
		"cmpl %[expect2], %[v2]\n\t"
		"jnz %l[cmpfail]\n\t"
		RSEQ_INJECT_ASM(5)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
		"cmpl %[v], %[expect]\n\t"
		"jnz %l[error2]\n\t"
		"cmpl %[expect2], %[v2]\n\t"
		"jnz %l[error3]\n\t"
#endif
		"movl %[newv], %%eax\n\t"
		/* final store */
		"movl %%eax, %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(6)
		RSEQ_ASM_DEFINE_ABORT(4, "", abort)
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* cmp2 input */
		  [v2]			"m" (*v2),
		  [expect2]		"r" (expect2),
		  /* final store input */
		  [v]			"m" (*v),
		  [expect]		"r" (expect),
		  [newv]		"m" (newv)
		: "memory", "cc", "eax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2, error3
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("1st expected value comparison failed");
error3:
	rseq_bug("2nd expected value comparison failed");
#endif
}

/* TODO: implement a faster memcpy. */
static inline __attribute__((always_inline))
int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
				 void *dst, void *src, size_t len,
				 intptr_t newv, int cpu)
{
	uint32_t rseq_scratch[3];

	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		"movl %[src], %[rseq_scratch0]\n\t"
		"movl %[dst], %[rseq_scratch1]\n\t"
		"movl %[len], %[rseq_scratch2]\n\t"
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"movl %[expect], %%eax\n\t"
		"cmpl %%eax, %[v]\n\t"
		"jnz 5f\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
		"movl %[expect], %%eax\n\t"
		"cmpl %%eax, %[v]\n\t"
		"jnz 7f\n\t"
#endif
		/* try memcpy */
		"test %[len], %[len]\n\t" \
		"jz 333f\n\t" \
		"222:\n\t" \
		"movb (%[src]), %%al\n\t" \
		"movb %%al, (%[dst])\n\t" \
		"inc %[src]\n\t" \
		"inc %[dst]\n\t" \
		"dec %[len]\n\t" \
		"jnz 222b\n\t" \
		"333:\n\t" \
		RSEQ_INJECT_ASM(5)
		"movl %[newv], %%eax\n\t"
		/* final store */
		"movl %%eax, %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(6)
		/* teardown */
		"movl %[rseq_scratch2], %[len]\n\t"
		"movl %[rseq_scratch1], %[dst]\n\t"
		"movl %[rseq_scratch0], %[src]\n\t"
		RSEQ_ASM_DEFINE_ABORT(4,
			"movl %[rseq_scratch2], %[len]\n\t"
			"movl %[rseq_scratch1], %[dst]\n\t"
			"movl %[rseq_scratch0], %[src]\n\t",
			abort)
		RSEQ_ASM_DEFINE_CMPFAIL(5,
			"movl %[rseq_scratch2], %[len]\n\t"
			"movl %[rseq_scratch1], %[dst]\n\t"
			"movl %[rseq_scratch0], %[src]\n\t",
			cmpfail)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_DEFINE_CMPFAIL(6,
			"movl %[rseq_scratch2], %[len]\n\t"
			"movl %[rseq_scratch1], %[dst]\n\t"
			"movl %[rseq_scratch0], %[src]\n\t",
			error1)
		RSEQ_ASM_DEFINE_CMPFAIL(7,
			"movl %[rseq_scratch2], %[len]\n\t"
			"movl %[rseq_scratch1], %[dst]\n\t"
			"movl %[rseq_scratch0], %[src]\n\t",
			error2)
#endif
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* final store input */
		  [v]			"m" (*v),
		  [expect]		"m" (expect),
		  [newv]		"m" (newv),
		  /* try memcpy input */
		  [dst]			"r" (dst),
		  [src]			"r" (src),
		  [len]			"r" (len),
		  [rseq_scratch0]	"m" (rseq_scratch[0]),
		  [rseq_scratch1]	"m" (rseq_scratch[1]),
		  [rseq_scratch2]	"m" (rseq_scratch[2])
		: "memory", "cc", "eax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

/* TODO: implement a faster memcpy. */
static inline __attribute__((always_inline))
int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
					 void *dst, void *src, size_t len,
					 intptr_t newv, int cpu)
{
	uint32_t rseq_scratch[3];

	RSEQ_INJECT_C(9)

	__asm__ __volatile__ goto (
		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
		"movl %[src], %[rseq_scratch0]\n\t"
		"movl %[dst], %[rseq_scratch1]\n\t"
		"movl %[len], %[rseq_scratch2]\n\t"
		/* Start rseq by storing table entry pointer into rseq_cs. */
		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
		RSEQ_INJECT_ASM(3)
		"movl %[expect], %%eax\n\t"
		"cmpl %%eax, %[v]\n\t"
		"jnz 5f\n\t"
		RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
		"movl %[expect], %%eax\n\t"
		"cmpl %%eax, %[v]\n\t"
		"jnz 7f\n\t"
#endif
		/* try memcpy */
		"test %[len], %[len]\n\t" \
		"jz 333f\n\t" \
		"222:\n\t" \
		"movb (%[src]), %%al\n\t" \
		"movb %%al, (%[dst])\n\t" \
		"inc %[src]\n\t" \
		"inc %[dst]\n\t" \
		"dec %[len]\n\t" \
		"jnz 222b\n\t" \
		"333:\n\t" \
		RSEQ_INJECT_ASM(5)
		"lock; addl $0,-128(%%esp)\n\t"
		"movl %[newv], %%eax\n\t"
		/* final store */
		"movl %%eax, %[v]\n\t"
		"2:\n\t"
		RSEQ_INJECT_ASM(6)
		/* teardown */
		"movl %[rseq_scratch2], %[len]\n\t"
		"movl %[rseq_scratch1], %[dst]\n\t"
		"movl %[rseq_scratch0], %[src]\n\t"
		RSEQ_ASM_DEFINE_ABORT(4,
			"movl %[rseq_scratch2], %[len]\n\t"
			"movl %[rseq_scratch1], %[dst]\n\t"
			"movl %[rseq_scratch0], %[src]\n\t",
			abort)
		RSEQ_ASM_DEFINE_CMPFAIL(5,
			"movl %[rseq_scratch2], %[len]\n\t"
			"movl %[rseq_scratch1], %[dst]\n\t"
			"movl %[rseq_scratch0], %[src]\n\t",
			cmpfail)
#ifdef RSEQ_COMPARE_TWICE
		RSEQ_ASM_DEFINE_CMPFAIL(6,
			"movl %[rseq_scratch2], %[len]\n\t"
			"movl %[rseq_scratch1], %[dst]\n\t"
			"movl %[rseq_scratch0], %[src]\n\t",
			error1)
		RSEQ_ASM_DEFINE_CMPFAIL(7,
			"movl %[rseq_scratch2], %[len]\n\t"
			"movl %[rseq_scratch1], %[dst]\n\t"
			"movl %[rseq_scratch0], %[src]\n\t",
			error2)
#endif
		: /* gcc asm goto does not allow outputs */
		: [cpu_id]		"r" (cpu),
		  [current_cpu_id]	"m" (__rseq_abi.cpu_id),
		  [rseq_cs]		"m" (__rseq_abi.rseq_cs),
		  /* final store input */
		  [v]			"m" (*v),
		  [expect]		"m" (expect),
		  [newv]		"m" (newv),
		  /* try memcpy input */
		  [dst]			"r" (dst),
		  [src]			"r" (src),
		  [len]			"r" (len),
		  [rseq_scratch0]	"m" (rseq_scratch[0]),
		  [rseq_scratch1]	"m" (rseq_scratch[1]),
		  [rseq_scratch2]	"m" (rseq_scratch[2])
		: "memory", "cc", "eax"
		  RSEQ_INJECT_CLOBBER
		: abort, cmpfail
#ifdef RSEQ_COMPARE_TWICE
		  , error1, error2
#endif
	);
	return 0;
abort:
	RSEQ_INJECT_FAILED
	return -1;
cmpfail:
	return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
	rseq_bug("cpu_id comparison failed");
error2:
	rseq_bug("expected value comparison failed");
#endif
}

#endif /* !RSEQ_SKIP_FASTPATH */

#endif

{'repo_name': 'microsoft/WSL2-Linux-Kernel', 'stars': '3852', 'repo_language': 'C', 'file_name': 'sun4i-ss-core.c', 'mime_type': 'text/x-c', 'hash': 3258231061303205100, 'source_dataset': 'data'}


################################################################################
#
#  Copyright 2014-2016 Eric Lacombe <eric.lacombe@security-labs.org>
#
################################################################################
#
#  This file is part of fuddly.
#
#  fuddly is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  fuddly is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with fuddly. If not, see <http://www.gnu.org/licenses/>
#
################################################################################

from __future__ import print_function

import os
import sys
import subprocess
import re
import inspect
import uuid

class Term(object):

    def __init__(self, name=None, keepterm=False, xterm_args=None, xterm_prg_name='x-terminal-emulator'):
        self.name = name
        self.keepterm = keepterm
        self.xterm_args = xterm_args
        self.xterm_prg_name = xterm_prg_name

    def start(self):
        self.pipe_path = os.sep + os.path.join('tmp', 'fuddly_term_'+str(uuid.uuid4()))
        if not os.path.exists(self.pipe_path):
            os.mkfifo(self.pipe_path)
        self.cmd = [self.xterm_prg_name]
        if self.name is not None:
            self.cmd.extend(['-title',self.name])
        if self.xterm_args:
            self.cmd.extend(self.xterm_args)
        if self.keepterm:
            self.cmd.append('--hold')
        self.cmd.extend(['-e', 'tail -f {:s}'.format(self.pipe_path)])
        self._p = None

    def _launch_term(self):
        self._p = subprocess.Popen(self.cmd)

    def stop(self):
        if not self.keepterm and self._p is not None and self._p.poll() is None:
            self._p.kill()
        self._p = None
        try:
            os.remove(self.pipe_path)
        except FileNotFoundError:
            pass

    def print(self, s, newline=False):
        s += '\n' if newline else ''
        if self._p is None or self._p.poll() is not None:
            self._launch_term()
        with open(self.pipe_path, "w") as input_desc:
            input_desc.write(s)

    def print_nl(self, s):
        self.print(s, newline=True)

def ensure_dir(f):
    d = os.path.dirname(f)
    if not os.path.exists(d):
        os.makedirs(d)

def ensure_file(f):
    if not os.path.isfile(f):
        open(f, 'a').close()

def chunk_lines(string, length):
    l = string.split(' ')
    chk_list = []
    full_line = ''
    for wd in l:
        full_line += wd + ' '
        if len(full_line) > (length - 1):
            chk_list.append(full_line)
            full_line = ''
    if full_line:
        chk_list.append(full_line)
    # remove last space char
    if chk_list:
        chk_list[-1] = (chk_list[-1])[:-1]
    return chk_list

def find_file(filename, root_path):
    for (dirpath, dirnames, filenames) in os.walk(root_path):
        if filename in filenames:
            return dirpath + os.sep + filename
    else:
        return None

def retrieve_app_handler(filename):
    mimetype = subprocess.check_output(['xdg-mime', 'query', 'filetype', filename])[:-1]
    desktop_file = subprocess.check_output(['xdg-mime', 'query', 'default', mimetype])[:-1]

    file_path = find_file(desktop_file.decode(), root_path='~/.local/share/applications/')
    if file_path is None:
        file_path = find_file(desktop_file.decode(), root_path='/usr/share/applications/')

    if file_path is None:
        return None

    with open(file_path, 'r') as f:
        buff = f.read()
        result = re.search("Exec=(.*)", buff)
        app_name = result.group(1).split()[0]
    return app_name

if sys.version_info[0] > 2:
    def get_caller_object(stack_frame=2):
        caller_frame_record = inspect.stack()[stack_frame]
        return caller_frame_record.frame.f_locals['self']
else:
    def get_caller_object(stack_frame=2):
        caller_frame_record = inspect.stack()[stack_frame]
        return caller_frame_record[0].f_locals['self']

{'repo_name': 'k0retux/fuddly', 'stars': '156', 'repo_language': 'Python', 'file_name': 'external_modules.py', 'mime_type': 'text/x-python', 'hash': -7752244389581952671, 'source_dataset': 'data'}